diff --git a/0805/README.md b/0805/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f27414c9ff0420c9bb5939b3b47f413afa70cd15 --- /dev/null +++ b/0805/README.md @@ -0,0 +1,103 @@ +# C Preprocessor + +전처리기(preprocessor)는 전처리(.c -> .i)를 해주는 도구이다. 전처리는 .h에 있는 텍스트들을 .c에 치환(붙여넣기)해주는 과정이다. C Preprocessor는 CPP로 줄여쓰기도 한다. + +### Including files + +* `#include <filename>` +표준 헤더 파일을 include하는 방식으로 표준 라이브러리들이 모여있는 폴더에서 헤더 파일을 검색해서 include한다. + +* `#include "filename"` +사용자 헤더 파일을 include하는 방식으로 현재 소스 파일이 위치한 폴더에서 헤더 파일을 검색해서 include한다. + +### Conditional compilation + +#if, #ifdef, #ifndef, #else, #elif, #endif는 조건부 컴파일을 할 수 있게 한다. 조건이 맞지 않으면 그 부분이 컴파일에서 제외된다. 즉, 소스 자체가 없는 효과가 있다. +#error을 사용하여 컴파일을 실패하게 할 수도 있다. + +### Macro definition + +특정 숫자, 함수, 프로그램 블록을 다른 형태로 변환 지정한다. 변환은 원래 한 줄만 가능하지만 \를 사용하여 여러 줄을 연결할 수 있다. + +* `#define <identifier> <replacement token list>` +대상변환형(Object-like macros)이라고 하며 identifier를 replacement token list로 변환한다. + +* `#define <identifier>(<parameter list>) <replacement token list>` +유사함수변환형(Function-like macros)이라고 하며 identifier와 parameter list를 replacement token list로 변환한다. + +* `#undef <identifier>` +#undef를 사용해 정의된 매크로를 무효화할 수도 있다. + +```c +#define f(a) a*a +b = f(20+13) // b = 293 +``` +전처리는 단순히 텍스트를 치환하는 것이기 때문에 위의 코드를 실행할 시 +```c +b = 20 + 13 * 20 + 13 +``` +이렇게 치환되므로 괄호를 최대한 많이 써주는 것이 좋다. +```c +#define f(a) ((a)*(a)) +b = f(20+13) // b = 1089 +``` + +### etc. + +* #pragma once +`#pragma once`를 사용하여 여러번 include하는 것을 방지할 수 있다. + +* Token stringification +`#define <identifier>(<parameter>) #parameter` +#연산자는 token을 문자열 상수로 변환한다. + +* Token concatenation +`#define <identifier>(<parameter>) parameter##string` +##연산자는 두 token을 하나로 연결하여 변환한다. + +* Debuging macros +디버깅을 하면서 어느 부분에서 에러가 났는 지 알려준다. + + * __FILE\_\_ + 에러가 발생한 파일 경로 + * __LINE\_\_ + 에러가 발생한 라인 + * __FUNCTION\_\_ + 에러가 발생한 함수 + +# Multiple file compile + +* func.h +``` +#define SQAURE(a) ((a)*(a)) +extern int func(int a); +``` + +* func.c +``` +#include "func.h" + +int func(int a) +{ + return(a * 10); +} +``` + +* main.c +``` +#include <stdio.h> +#include "func.h" + +int main() +{ + printf("func(100): %d SQUARE(10): %d\n", func(100), SQUARE(10)); + return 0; +} +``` + +보통 이런 식으로 코드를 작성하고 + +``` +$ gcc main.c func.c +``` +이렇게 컴파일, 링크하여 실행 파일을 실행한다. \ No newline at end of file diff --git a/0805/three_files/func.c b/0805/three_files/func.c new file mode 100644 index 0000000000000000000000000000000000000000..8f2a8a6e40a91256acba971276d98aaa8b544392 --- /dev/null +++ b/0805/three_files/func.c @@ -0,0 +1,11 @@ +#include "func.h" + +int func1(int a) +{ + return (a * 10); +} + +int func2(int a) +{ + return (a * 2); +} \ No newline at end of file diff --git a/0805/three_files/func.h b/0805/three_files/func.h new file mode 100644 index 0000000000000000000000000000000000000000..0aa7479313d3ebc2e5afe4a49b3b8621d31e8516 --- /dev/null +++ b/0805/three_files/func.h @@ -0,0 +1,3 @@ +#pragma once +#define DF(a) ((a)*(a)) +extern int func1(int x); \ No newline at end of file diff --git a/0805/three_files/main.c b/0805/three_files/main.c new file mode 100644 index 0000000000000000000000000000000000000000..2f2c8826140c1448b4307dd70d64a9d84840555c --- /dev/null +++ b/0805/three_files/main.c @@ -0,0 +1,18 @@ +#include <stdio.h> +#include "func.h" + +int func_name_or_id() +{ +#ifdef PRINT_ID + printf("201920756"); + return 0; +#else + printf("�����"); + return 1; +#endif +} + +int main() +{ + func_name_or_id(); +}