diff --git a/README.md b/README.md index bfd5ab7374c8bd43b373e12e8e65a9bccf7d27fb..15087e598aea82ea339850b46ef082f7a5dea963 100644 --- a/README.md +++ b/README.md @@ -1012,6 +1012,7 @@ In addValue C -300 : 140732089039380 7ffebe2cfa14 * -c : .o 파일 생성 (assembly) * -E : .c 파일 생성 * -O : 최적화 + * -S : 전처리된 파일을 어셈블리 파일로 컴파일하고 멈춤 (.s 파일 생성) * --32, --64 : 32비트 컴파일(64비트 컴퓨터에서도 컴파일 가능), 64비트 컴파일 * -Dmacro : #define 가능 @@ -1019,16 +1020,6 @@ In addValue C -300 : 140732089039380 7ffebe2cfa14 * 코드는 위의 Pointer / Address 참고 * 수식하고자 하는 문자-수식어 순으로 작성함 -### int const * vs int * const -* int const * - * 포인터가 const int형을 가리킴 - * 포인터 값은 변경이 가능 -> 다른 것을 가리킬 수 있음 - * int 값은 const로 선언되어 변경이 불가능함 -* int * const - * const 포인터가 int형을 가리킴 - * 포인터의 값은 변경이 불가능 - * int형 변경 가능 - ``` const int a = 100; int *p = &a; @@ -1134,8 +1125,204 @@ int main() * 표현 범위와 구조에 대해 명확하게 표현 * 메모리 할당 -> 주소로 접근하면 const 값 변경 가능 +### 조건부 컴파일 +* 정해진 조건에 따라 소스 코드의 컴파일 여부를 제어하는 전처리기 +* #define으로 매크로의 이름을 정의 +* __DATE__, __TIME__, __FILE__, __LINE__는 컴파일러에서 제공하는 매크로 + * __DATE__: 컴파일한 날짜(실행 시점의 현재 날짜가 아님) + * __TIME__: 컴파일한 시간(실행 시점의 현재 시간이 아님) + * __FILE__: __FILE__ 매크로가 사용된 헤더, 소스 파일 + * __LINE__: __LINE__ 매크로가 사용된 줄 번호 + +* #ifdef와 #endif 지시자를 사용하여 정의 +``` +#ifdef 매크로 // 매크로가 정의되어 있다면 #ifdef, #endif 사이의 코드를 컴파일 +코드 +#endif +``` + +* #ifndef와 #endif 지시자를 사용하여 정의 +``` +#ifndef 매크로 // 매크로가 정의되어 있지 않다면 #ifndef, #endif 사이의 코드를 컴파일 +코드 +#endif +``` +``` +#include <stdio.h> +#define DEBUG + +int main() { +#ifdef DEBUG // #ifdef는 위에서 매크로가 선언된 경우 내부 코드가 실행됨 + printf("Debug : %s \t %s \t %s \t %d \n", __DATE__, __TIME__, __FILE__, __LINE__); +#endif + + char name[] = "Nayoung"; + int age = 21; + +#ifndef INTRO // #ifndef는 위에서 매크로가 선언되지 않은 경우 내부 코드를 실행함 + printf("Name : %s \t Age : %d \n", name, age); +#endif + return 0; +} +``` +코드에 #define INTRO를 추가하면 #ifndef 내부 코드는 실행되지 않음 + +* 값 또는 식 판별 후 조건부 컴파일 +``` +#if 값 또는 식 +코드 +#endif +``` +``` +#include <stdio.h> +#define DEBUG_LEVEL 2 + +int main() +{ +#if DEBUG_LEVEL >= 2 // DEBUG_LEVEL이 2보다 크거나 같으면 #if, #endif 사이의 코드를 컴파일 + printf("Debug Level 2 \n"); +#endif + +#if 1 // 조건이 항상 참이므로 내부 코드 컴파일 + printf("It is 1 \n"); +#endif + +#if 0 // 조건이 항상 거짓이므로 내부 코드 컴파일하지 않음 + printf("It is 0 \n"); +#endif + + return 0; +} +``` +* defined +``` +#if (defined DEBUG || defined TEST) && !defined (VERSION_10) +// DEBUG 또는 TEST가 정의되어 있으면서 VERSION_10이 정의되어 있지 않을 때 +``` + +### #include +* 전처리기 +* 헤더 파일(.h)과 소스 파일(.c)를 포함 +``` +#include <파일> +#include "파일" +``` +* <> + * C언어 표준 라이브러리의 헤더 파일을 포함할 때 사용 +* " " + * 현재 소스 파일을 기준으로 헤더 파일을 포함 + * 헤더 파일을 찾지 못할 경우 컴파일 옵션에서 지정한 헤더 파일 경로를 따름 + +### extern +* 다른 소스 파일의 전역 변수를 사용할 수 있음 + +### CPP - include file +* #include file as text + * #include <stdio.h> or "file.h" +* gcc Option - I + * Include location - ./usr/include/ + * Default include location +* Prevent multiple include + * #pragma once (로딩 한번만) +``` + #ifndef _MATH_ + #include <math.h> + #endif +``` + ## **Lecture 08** ### Linux Command 1. ^(위 명령에서 잘못 입력한 문자)^ (바꿀 문자) * 위 명령에서 특정 문자를 잘못 입력한 경우 사용함 + +### .o file + + +### GCC Optimization +* -O0(기본값) + * 최적화 수행 안 함 +* -O, -O1 + * 만들어지는 .o, .out 파일을 가능한 작게 하면서 컴파일 시간이 오래걸리지 않는 범위에서 최적화 수행 +* -O2 + * 만들어지는 코드가 가능한 빠르게 수행되지만 코드의 크기가 너무 커지지않는 범위에서 최적화 수행 +* -O3 + * 코드의 크기 신경 쓰지 않고 빠른 코드를 만들어내기 위한 최적화 수행 + * -O2 최적화에 인라인 함수와 레지스터에 대한 최적화 추가로 수행 + * -O2 코드보다 빠르다는 보장은 없음 + * 인라인 함수 (inline) + +``` + inline 반환값자료형 함수이름(매개변수자료형 매개변수이름) + { + } +``` + * 호출 없이 함수의 코드를 그 자리에서 실행 + * 컴파일러는 함수를 사용하는 부분에 함수의 코드를 복제해서 넣어줌 + * 함수 호출 과정이 없어 속도가 비교적 빠름 +``` + #include <stdio.h> + inline int add(int a, int b) + { + return a+b; + } + int main() + { + int num1; + /* + num1 = inline int add(10, 20) + { + return 10 + 20; + } + */ + // 주석 부분을 컴파일러가 함수를 복제해서 넣어줌! + printf("%d", num1); + } +``` +* -Os + * -O2 최적화 기능 사용 + * 코드 크기를 증가시키는 최적화는 생략 + + +### #error +* ``` #error 토큰 문자열 ``` +* 컴파일 시간에 사용자 지정 오류 메시지를 내보낸 다음 컴파일을 종료 +* 프로그램 불일치나 제한된 내용에 접근하는 경우 개발자에게 고치도록 알림 +* 명확한 에러 설명 혹은 프로그램의 안전성을 위해 사용 + +### Token stringification (토큰 문자열화) +``` +#define str(s) #s +str(p = "foo\n";) // outputs "p = \"foo\n\";" +str(\n) // outputs "\n" + +#define xstr(s) str(s) +#define str(s) #s +#define foo 4 +str (foo) // outputs "foo" +xstr (foo) // outputs "4" +``` +* #define #s을 통해 문자열로 바꿔줌 + * 항상 #s일 필요는 없음 str(문자) 내부의 문자와 동일 +* 출력 형태를 다양하게 하는 매크로를 만들 때 유용 (%c, %d, %s 등) ++ 토큰 + * 프로그램을 구성하고 있는 문법적으로 의미 있는 최소 단위 + +### Token Concatenation (토큰 붙여넣기) +``` +#define DECLARE_STURCT_TYPE(name) typedef struct name##_s name##_t + +DECLARE_STRUCT_TYPE(g_object); +// Outputs: typedef struct +g_object_s g_object_t; + +//다른 예제 +#include <stdio.h> +#define paster( n ) printf( "token" #n " = %d", token##n ) +int token9 = 9; + +int main() +{ + paster(9); // output : token9 = 9 +} +```