맨위로가기

C 전처리기

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

C 전처리기는 1973년경 C 언어에 도입된 기능으로, 파일 포함, 매크로 확장, 조건부 컴파일 등을 수행한다. C 표준의 번역 단계 중 처음 4단계를 담당하며, 트라이그래프 대체, 라인 결합, 토큰화, 매크로 확장 및 지시어 처리를 거친다. `#include`를 사용하여 다른 파일의 내용을 현재 위치에 포함시키고, `#if`, `#ifdef` 등의 지시어를 통해 조건부로 코드를 컴파일하거나 제외할 수 있다. `#define`을 사용하여 매크로를 정의하고 확장하며, 특수한 매크로인 `__FILE__`, `__LINE__` 등을 통해 디버깅 정보를 제공한다. C23 표준에서는 바이너리 리소스 포함을 위한 `#embed` 지시어가 도입될 예정이다. C 전처리기는 C, C++, Objective-C 등에서 사용되며, 컴파일러별로 다양한 확장 기능을 제공한다. 또한 다른 언어에서도 사용될 수 있지만, 입력 언어가 C와 유사해야 한다.

더 읽어볼만한 페이지

  • 매크로 프로그래밍 언어 - TeX
    TeX는 도널드 커누스가 개발한 수학, 과학, 공학 분야의 고품질 문서 출력을 위한 조판 시스템이며, 수학 수식 조판에 특화된 매크로 시스템과 높은 확장성을 제공한다.
  • 매크로 프로그래밍 언어 - M4 (프로그래밍 언어)
    M4는 1977년 데니스 리치와 브라이언 커니건이 개발한 매크로 프로세싱 프로그래밍 언어이며, 텍스트 재사용, 파일 포함, 문자열 조작 등 다양한 기능을 제공하고 튜링 완전성을 갖춘 언어이다.
  • C 프로그래밍 언어 - C (프로그래밍 언어)
    C는 하드웨어 제어와 이식성이 뛰어난 고급 절차적 프로그래밍 언어로서, 다양한 분야에서 사용되며 후속 언어에 영향을 주었고, 성능과 효율성이 높지만 안전성 문제 개선이 필요한 언어이다.
  • C 프로그래밍 언어 - 헤더 파일
    헤더 파일은 프로그래밍 언어에서 코드 재사용성, 모듈화, 컴파일 시간 단축에 기여하며 함수 프로토타입, 변수 선언 등을 포함하고 `#include` 지시어로 소스 코드에 포함되어 사용되는 파일이다.
C 전처리기
기본 정보
종류컴퓨터 프로그램, 컴파일러
개발자여러 개발자
발표일1972년
최신 버전GNU cpp 13.2 (2023년 8월 2일)
상태활발
추가 정보
운영체제크로스 플랫폼
언어C, C++, Objective-C
종류전처리기
라이선스GNU GPL (일부)

2. 역사

C 전처리기는 1973년경 앨런 스나이더(Alan Snyder)의 제안과 BCPLPL/I에서 사용 가능한 파일 포함 메커니즘의 유용성을 인식하여 C에 도입되었다. 초기 버전은 파일 포함과 단순 문자열 교체만 제공했으며, 매개변수가 없는 매크로를 위해 `#include`와 `#define`을 사용했다. 이후 마이크 레스크(Mike Lesk)와 존 라이저에 의해 매개변수가 있는 매크로 및 조건부 컴파일 기능을 포함하도록 확장되었다.[2]

C 전처리기는 1959년 더글러스 이스트우드와 더글러스 맥길로이(Douglas McIlroy)에 의해 시작된 벨 연구소(Bell Labs)의 긴 매크로 언어 전통의 일부였다.[3]

3. 번역 단계

전처리(preprocessor)는 C 표준에 명시된 여덟 단계의 "번역 단계" 중 처음 네 단계로 정의된다.

1. 트라이그래프 대체: 전처리기는 트라이그래프 시퀀스를 해당 문자로 대체한다. 이 단계는 C23에서 C++17의 단계를 따라 제거될 예정이다.[1]

2. 라인 결합: 이스케이프 문자로 이스케이프된 개행 문자 시퀀스로 계속되는 물리적 소스 라인은 논리적 라인을 형성하기 위해 '결합'된다.[1]

3. 토큰화: 전처리기는 결과를 '전처리 토큰'과 공백 문자로 나눈다. 주석은 공백으로 대체한다.[1]

4. 매크로 확장 및 지시어 처리: 파일 포함 및 조건부 컴파일을 포함한 전처리 지시어 라인이 실행된다. 전처리기는 매크로를 동시에 확장하고, 1999년 버전의 C 표준부터는 `_Pragma` 연산자를 처리한다.[1]

4. 파일 포함

`#include` 지시어는 다른 소스 파일을 현재 파일에 포함시켜 하나의 파일처럼 컴파일되도록 하는 기능이다. 보통 IDE 개발 환경에서는 프로젝트 단위로 여러 파일을 관리하고 컴파일하여 실행 파일을 생성하는데, 이때 `#include`를 사용하여 서로 다른 파일 간에 함수, 변수 선언 등을 연결한다.

예시:

```cpp

#include

int main(void)

{

printf("Hello, world!\n");

return 0;

}

```

위 코드에서 `#include `는 `stdio.h` 파일의 내용을 현재 위치에 포함시킨다. `stdio.h`에는 `printf()` 함수의 선언이 포함되어 있어 컴파일러가 `printf()` 함수를 올바르게 호출할 수 있게 된다.[1]

`#include` 지시어는 `<>` (꺾쇠 괄호) 또는 `""` (큰따옴표)를 사용하여 파일 이름을 감쌀 수 있다.


  • `<>`: 표준 컴파일러 include 경로에서 파일을 찾는다.
  • `""`: 현재 소스 파일 디렉터리를 포함하여 확장된 경로에서 파일을 찾는다.


C 컴파일러 및 프로그래밍 환경은 include 파일을 찾을 위치를 지정하는 기능을 제공하며, 이는 makefile을 통해 매개변수화된 명령줄 플래그를 사용하여 설정할 수 있다. 이를 통해 운영 체제에 따라 다른 include 파일 집합을 사용할 수 있다.[1]

관례상 include 파일은 `.h` 또는 `.hpp` 확장자를 사용하지만, 반드시 지켜야 하는 것은 아니다. `.def` 확장자는 여러 번 포함되도록 설계된 파일을 나타내며, `#include "icon.xbm"`과 같이 XBM 이미지 파일(C 소스 파일이기도 함)을 참조할 수도 있다.[1]

`#include`를 사용할 때는 이중 포함을 방지하기 위해 `#include` 가드 또는 `#pragma once`를 사용하는 것이 일반적이다.[1]

5. 조건부 컴파일

`#if`, `#ifdef`, `#ifndef`, `#else`, `#elif`, `#endif`는 특정 조건에 따라 코드 블록을 컴파일하거나 제외하는 조건부 컴파일 기능을 제공한다.[4] 조건이 맞지 않으면 해당 코드는 컴파일되지 않아 마치 소스 코드 자체가 없는 것과 같은 효과를 낸다.

예시:

```cpp

#if VERBOSE >= 2

print("trace message");

#endif

```

위 코드에서 `VERBOSE` 값이 2보다 크거나 같으면 `print("trace message");` 코드가 컴파일되고, 그렇지 않으면 컴파일되지 않는다. `VERBOSE` 값은 미리 정의되어 있어야 한다.

조건부 컴파일을 활용하면 다양한 환경에 맞게 코드를 컴파일할 수 있다.

```cpp

#ifdef __unix__ /* __unix__는 일반적으로 유닉스 시스템을 대상으로 하는 컴파일러에 의해 정의됩니다 */

# include

#elif defined _WIN32 /* _WIN32는 일반적으로 32 또는 64비트 윈도우 시스템을 대상으로 하는 컴파일러에 의해 정의됩니다 */

# include

#endif

```

위 코드는 운영체제가 UNIX 환경(`__unix__`가 정의된 경우)이면 `` 파일을, 윈도우 환경(`_WIN32`가 정의된 경우)이면 `` 파일을 포함한다.

`#if`와 `defined`를 함께 사용하면 더 복잡한 조건부 컴파일도 가능하다.

```cpp

#if !(defined __LP64__ || defined __LLP64__) || defined _WIN32 && !defined _WIN64

// 우리는 32비트 시스템을 위해 컴파일하고 있습니다.

#else

// 우리는 64비트 시스템을 위해 컴파일하고 있습니다.

#endif

```

`#error` 지시어를 사용하면 컴파일을 강제로 실패시킬 수 있다.

```cpp

#if RUBY_VERSION == 190

#error 1.9.0은 지원되지 않습니다.

#endif

```

위 코드는 `RUBY_VERSION`이 190이면 컴파일 오류를 발생시킨다.

윈도우를 대상으로 하는 대부분의 컴파일러는 `_WIN32` 매크로를 암묵적으로 정의한다.[4] 이를 이용하면 윈도우 시스템을 대상으로 할 때만 코드가 컴파일되도록 할 수 있다. `_WIN32` 매크로를 정의하지 않는 컴파일러의 경우 `-D_WIN32` 옵션을 사용하여 컴파일러 명령줄에서 지정할 수 있다.

6. 매크로 정의 및 확장

`#define` 지시어는 특정 식별자를 다른 토큰으로 대체하는 매크로를 정의하는 데 사용된다. 이러한 매크로는 객체 유사 매크로와 함수 유사 매크로 두 가지 유형이 있다. 객체 유사 매크로는 주로 상수에 이름을 붙여 코드의 가독성을 높이는 데 사용된다.[21] 예를 들어, `#define PI 3.14159`와 같이 정의하면 코드 내에서 `PI`라는 식별자를 사용할 때마다 `3.14159`로 대체된다. 이렇게 하면 숫자 자체를 사용하는 것보다 의미를 명확하게 전달할 수 있다.

함수 유사 매크로는 함수처럼 인수를 받아 더 복잡한 변환을 수행할 수 있다.[22] 예를 들어, `#define RADTODEG(x) ((x) * 57.29578)`와 같이 정의하면 `RADTODEG(34)`와 같은 코드는 `((34) * 57.29578)`로 확장된다. 이렇게 하면 코드를 간결하게 유지하고 반복을 줄일 수 있다.

`#undef` 지시어를 사용하면 정의된 매크로를 제거할 수 있다.[21][22] `#undef PI`와 같이 사용하면 `PI`에 대한 매크로 정의가 제거된다.

C++에서는 `const` 한정자나 `constexpr` 키워드를 사용하여 객체 유사 매크로와 유사한 기능을 수행할 수 있다.[5] `constexpr`는 컴파일 시간에 값을 계산하도록 지정하여 매크로처럼 사용할 수 있게 해준다.

C 전처리기는 1973년경 앨런 스나이더(Alan Snyder)의 제안으로 C에 도입되었으며, 초기에는 파일 포함과 단순 문자열 교체 기능만 제공했다.[2] 이후 마이크 레스크(Mike Lesk)와 존 라이저에 의해 기능이 확장되었다. C 전처리기는 더글러스 맥길로이(Douglas McIlroy) 등이 참여한 벨 연구소의 매크로 언어 전통을 계승한 것이다.[3]

매크로를 정의할 때는 연산자 우선순위로 인한 오류를 방지하기 위해 주의해야 한다. 매크로 인자와 전체 표현식을 괄호로 묶는 것이 일반적인 방법이다. 예를 들어 `RADTODEG(r + 1)`은 `((r + 1) * 57.29578)`로 확장되어 올바른 계산 결과를 얻을 수 있다.

6. 1. 확장 순서

함수형 매크로 확장은 다음 단계로 수행된다.

1. 문자열화 연산자는 인수의 대체 목록의 텍스트 표현으로 대체된다. (확장 수행하지 않음).

2. 매개변수는 대체 목록으로 대체된다.(확장 수행하지 않음).

3. 연결 연산자는 두 피연산자의 연결된 결과로 대체된다. (결과 토큰을 확장하지 않음).

4. 매개변수에서 파생된 토큰이 확장된다.

5. 결과 토큰은 정상적으로 확장된다.

이는 놀라운 결과를 초래할 수 있다.

```cpp

#define HE HI

#define LLO _THERE

#define HELLO "HI THERE"

#define CAT(a,b) a##b

#define XCAT(a,b) CAT(a,b)

#define CALL(fn) fn(HE,LLO)

CAT(HE, LLO) // "HI THERE", 연결은 일반 확장 전에 수행된다.

XCAT(HE, LLO) // HI_THERE, 매개변수("HE" 및 "LLO")에서 파생된 토큰이 먼저 확장된다.

CALL(CAT) // "HI THERE", 이는 CAT(a,b)로 평가되기 때문이다.

7. 특수 매크로 및 지시어

C 전처리기는 프로그램 실행에 필요한 여러 특수 매크로와 지시어를 제공한다.


  • `__FILE__`과 `__LINE__`: 이 매크로들은 각각 현재 소스 파일의 이름과 줄 번호를 나타낸다. 주로 디버깅 목적으로 사용되며, 오류 메시지를 출력할 때 파일 이름과 줄 번호를 함께 표시하여 문제 발생 위치를 쉽게 찾도록 도와준다.[6]


```cpp

#define DEBUGPRINT(_fmt, ...) fprintf(stderr, "[file %s, line %d]: " _fmt, __FILE__, __LINE__, __VA_ARGS__)

DEBUGPRINT("x = %d\n", x);

```

  • `#line`: 이 지시어는 `__FILE__`과 `__LINE__`의 값을 변경한다. 예를 들어 `#line 314 "pi.c"`는 이후 코드의 줄 번호를 314로, 파일 이름을 "pi.c"로 설정한다. 이는 다른 언어로 작성된 코드를 C 코드로 변환할 때 유용하다.[6]


```cpp

#line 314 "pi.c"

printf("line=%d file=%s\n", __LINE__, __FILE__); // 출력: line=314 file=pi.c

```

  • `__STDC__`, `__STDC_VERSION__`, `__cplusplus`: 이 매크로들은 각각 컴파일러가 표준 C를 따르는지 (`__STDC__`), 지원하는 표준 버전은 무엇인지 (`__STDC_VERSION__`), C++ 컴파일러인지 (`__cplusplus__`)를 나타낸다. 이를 통해 특정 표준에 맞는 코드를 작성하거나, C와 C++ 간 호환성을 확보할 수 있다.[6]

  • `__DATE__`와 `__TIME__`: 현재 날짜와 시간을 나타낸다.[6]

  • `__func__`: (C99 표준) 현재 함수의 이름을 나타낸다.[6]

  • 가변 매크로 (C99 표준): 가변 매크로는 `printf` 함수처럼 인수의 개수가 정해지지 않은 매크로를 정의할 수 있게 해준다. 로깅 함수를 만들 때 유용하다.[6]

  • X-Macros: 이 패턴은 헤더 파일에 매크로 호출 목록을 정의하고, 이 파일을 여러 번 포함시켜 코드 중복을 줄이는 기법이다. 주로 확장자가 `.def`인 파일에 정의된다.[6][7][8]

7. 1. 토큰 문자열화

`#` 연산자 ('''문자열화 연산자''' 또는 '''스트링화 연산자'''라고도 함)는 토큰을 C 문자열 리터럴로 변환하며, 따옴표나 백슬래시를 적절하게 이스케이프 처리한다.

예시:

```cpp

#define str(s) #s

str(p = "foo\n";) // 출력: "p = \"foo\\n\";"

str(\n) // 출력: "\n"

```

매크로 인수의 확장을 문자열화하려는 경우, 두 단계의 매크로를 사용해야 한다.

```cpp

#define xstr(s) str(s)

#define str(s) #s

#define foo 4

str (foo) // 출력: "foo"

xstr (foo) // 출력: "4"

```

매크로 인수는 추가 텍스트와 결합된 다음 문자열화될 수 없다. 그러나 일련의 인접한 문자열 상수와 문자열화된 인수는 작성할 수 있으며, C 컴파일러는 모든 인접한 문자열 상수를 하나의 긴 문자열로 결합한다.

7. 2. 토큰 연결

`##` 연산자 ("토큰 접합 연산자"라고도 함)는 두 개의 토큰을 하나의 토큰으로 연결한다.

```cpp

#define DECLARE_STRUCT_TYPE(name) typedef struct name##_s name##_t

DECLARE_STRUCT_TYPE(g_object); // 출력 결과: typedef struct g_object_s g_object_t

8. 사용자 정의 컴파일 오류

`#error` 지시어는 컴파일 오류를 발생시키고 지정된 메시지를 출력한다.

```c

#error "오류 메시지"

```

이 코드는 컴파일 시 "오류 메시지"라는 오류 메시지를 출력하고 컴파일을 중단시킨다. 주로 특정 조건이 충족되지 않았을 때 컴파일을 중단시키기 위해 사용된다.

9. 바이너리 리소스 포함

C23은 바이너리 리소스 포함을 위한 `#embed` 지시자를 도입할 예정이다.[9] 이를 통해 바이너리 파일(예: 이미지)을 프로그램에 포함할 수 있다. `#embed` 지시자는 지정된 리소스의 데이터에 해당하는 쉼표로 구분된 정수 목록으로 대체된다. 이는 `unsigned char` 유형의 배열이 `#embed` 지시자를 사용하여 초기화된 경우, fread를 사용하여 리소스를 배열에 쓴 것과 동일한 결과가 나타나는 것과 같다.

포함할 파일은 `#include`와 동일한 방식으로 지정할 수 있으며, 산형 괄호 또는 따옴표로 묶을 수 있다. 이 지시자는 파일 이름 뒤에 오는 동작을 사용자 정의하기 위해 특정 매개변수를 전달할 수 있도록 한다. C 표준은 다음과 같은 매개변수를 정의한다.


  • `limit`: 포함된 데이터의 너비를 제한한다. 주로 urandom과 같은 "무한" 파일에 사용하기 위한 것이다.
  • `prefix` 및 `suffix`: 포함된 데이터에 대한 접두사 및 접미사를 지정할 수 있으며, 이는 포함된 리소스가 비어 있지 않은 경우에만 사용된다.
  • `if_empty`: 리소스가 비어 있는 경우(파일이 비어 있거나 0의 제한이 지정된 경우 발생) 전체 지시자를 대체한다.


모든 표준 매개변수는 C23의 표준 속성과 마찬가지로 이중 밑줄로 묶을 수도 있다. 예를 들어, `__prefix__`는 `prefix`와 상호 교환이 가능하다.

10. 구현체

C, C++, Objective-C 구현은 모두 전처리기를 제공하며, 이는 해당 언어들의 필수적인 단계이다. 전처리기의 동작은 ISO C 표준과 같은 언어의 공식 표준에 의해 설명된다.[10]

구현은 자체적인 확장 및 변형을 제공할 수 있으며, 표준 준수 정도는 다를 수 있다. 정확한 동작은 호출 시 제공되는 명령줄 플래그에 따라 달라질 수 있다. 예를 들어, GNU C 전처리기는 특정 플래그를 통해 표준 준수를 높일 수 있다.[10]

10. 1. 컴파일러별 전처리기 기능

`#pragma` 지시어는 컴파일러 관련 지시어로, 컴파일러 제작자가 자체적인 목적으로 사용할 수 있다. 예를 들어, `#pragma`는 특정 오류 메시지 표시를 억제하고, 힙 및 스택 디버깅 등을 관리하는 데 자주 사용된다. OpenMP 병렬화 라이브러리를 지원하는 컴파일러는 `#pragma omp parallel for`를 사용하여 `for` 루프를 자동으로 병렬화할 수 있다.

C99는 부동 소수점 구현을 제어하는 데 사용되는 `#pragma STDC ...` 형식의 몇 가지 표준 `#pragma` 지시어를 도입했다. 매크로와 유사한 형태인 `_Pragma(...)`도 추가되었다.

  • 많은 구현에서 삼중 문자열을 지원하지 않거나 기본적으로 대체하지 않는다.
  • 많은 구현(예: GNU, Intel, Microsoft 및 IBM의 C 컴파일러)은 출력에 경고 메시지를 출력하지만 컴파일 프로세스를 중지하지 않는 비표준 지시어를 제공한다(C23[11] 및 C++23[12]은 이 목적으로 표준에 `#warning`을 추가한다). 일반적인 사용법은 호환성을 위해 포함된 더 이상 사용되지 않는 오래된 코드의 사용에 대해 경고하는 것이다. 예를 들면 다음과 같다.

  • * GNU, Intel 및 IBM

```

#warning "ABC는 더 이상 사용되지 않으므로 사용하지 마십시오. 대신 XYZ를 사용하십시오."

```

  • * Microsoft

```

#pragma message("ABC는 더 이상 사용되지 않으므로 사용하지 마십시오. 대신 XYZ를 사용하십시오.")

```

  • 일부 유닉스 전처리기에서는 프로그래밍에서 사용되는 어설션과는 거의 유사성이 없는 "어설션"을 전통적으로 제공했다.[13]
  • GCC는 동일한 이름의 헤더를 연결하기 위해 `#include_next`를 제공한다.[14]

10. 2. 언어별 전처리기 기능

Objective-C 전처리기는 `#include`와 유사하지만 파일을 한 번만 포함하는 `#import`를 가지고 있다. C에서 유사한 기능을 가진 일반적인 공급업체 프래그마는 `#pragma once`이다.

C++C++20부터 모듈을 위한 `import` 및 `module` 지시어를 가지고 있다.[15][16] 이 지시어들은 `#` 문자로 시작하지 않는 유일한 지시어이다. 대신, 선택적으로 `export`가 앞에 올 수 있으며, 각각 `import`와 `module`로 시작한다.

11. 기타 용도

C 전처리기는 컴파일러와 별도로 호출할 수 있어 다른 언어에서도 사용할 수 있다. 주목할 만한 예로는 현재는 사용되지 않는 imake 시스템과 포트란 전처리에 사용된 경우가 있다.[10] GNU 포트란 컴파일러는 특정 파일 확장자를 사용하면 포트란 코드를 컴파일하기 전에 자동으로 "전통 모드"(ISO C 이전의 C 전처리기처럼 작동) cpp를 호출한다.[17] 인텔은 ifort 컴파일러와 함께 사용할 수 있는 포트란 전처리기인 fpp를 제공하며, 이는 비슷한 기능을 제공한다.[18]

CPP는 대부분의 어셈블리 언어 및 알골 계열 언어와도 문제없이 작동한다. 이를 위해서는 언어 구문이 CPP 구문과 충돌하지 않아야 하는데, 이는 `#`으로 시작하는 줄이 없어야 하고, cpp가 문자열 리터럴로 해석하여 무시하는 큰따옴표가 그 외의 구문적 의미를 가지지 않아야 한다. "전통 모드"(ISO C 이전의 C 전처리기처럼 작동)는 일반적으로 더 관대하며 이러한 사용에 더 적합하다.[19]

C 전처리기는 튜링 완전성을 만족하지 않지만, 거의 근접한다. 재귀적인 계산을 지정할 수 있지만, 수행되는 재귀의 양에 고정된 상한이 있다.[20] 그러나 C 전처리기는 일반적인 목적의 프로그래밍 언어처럼 설계되지 않았으며, 성능도 좋지 않다. C 전처리기는 재귀 매크로, 인용에 따른 선택적 확장, 조건부 문자열 평가와 같은 다른 전처리기의 기능을 가지고 있지 않으므로, m4와 같은 보다 일반적인 매크로 프로세서에 비해 매우 제한적이다.

참조

[1] URL General-purpose text preprocessing with the C preprocessor. Featuring JavaScript https://gist.github.[...]
[2] Harvtxt Ritchie 1993
[3] Encyclopedia Bell SAP – SAP with conditional and recursive macros https://hopl.info/sh[...]
[4] URL List of predefined ANSI C and Microsoft C++ implementation macros. http://msdn.microsof[...]
[5] 웹사이트 General Constant Expressions for System Programming Languages, Proceedings SAC '10 http://www.stroustru[...] 2010-03-22
[6] 웹사이트 C "Preprocessor Trick For Implementing Similar Data Types" http://liw.iki.fi/li[...] 2011-01-09
[7] Journal The New C: X Macros http://www.ddj.com/c[...] 2001-05
[8] Journal Supermacros http://wanderinghors[...] 2004-08
[9] 웹사이트 WG14-N3017 : #embed – a scannable, tooling-friendly binary resource inclusion mechanism https://www.open-std[...] 2022-06-27
[10] 웹사이트 The C Preprocessor: Overview https://gcc.gnu.org/[...] 2016-07-17
[11] 웹사이트 WG14-N3096 : Draft for ISO/IEC 9899:2023 https://www.open-std[...] 2023-04-01
[12] 웹사이트 Working Draft, Standard for Programming Language C++ https://open-std.org[...] 2023-03-22
[13] URL GCC Obsolete features https://gcc.gnu.org/[...]
[14] 웹사이트 Wrapper Headers (The C Preprocessor) https://gcc.gnu.org/[...]
[15] 웹사이트 N4720: Working Draft, Extensions to C++ for Modules https://isocpp.org/f[...]
[16] 웹사이트 P1857R1 – Modules Dependency Discovery https://www.open-std[...]
[17] 웹사이트 1.3 Preprocessing and conditional compilation https://gcc.gnu.org/[...] GNU Project
[18] 웹사이트 Using the fpp Preprocessor https://software.int[...] Intel 2015-10-14
[19] 웹사이트 Overview (The C Preprocessor) https://gcc.gnu.org/[...]
[20] 웹사이트 Is the C99 preprocessor Turing complete? https://stackoverflo[...]
[21] 웹인용 Object-like macros http://gcc.gnu.org/o[...] 2012-11-25
[22] 웹인용 Function-like macros http://gcc.gnu.org/o[...] 2012-11-25



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com