전처리기는 소스파일의 일부분에 대해 컴파일에 조건부로 지원한다. 이 행동은 #if, #else, #elif, #ifdef, #ifndef, #elifdef, #elifndef, 그리고 #endif 지침에 대해 제어한다.
Syntax
#if
#ifdef
#ifndef
#elif
#elifdef
#elifndef
#else
#endif
Explanation
조건부 전처리 블록은 #if, #ifdef 또는 #ifndef 지침으로 시작한다, 그러면 선택적으로 #elif, #elifdef, 또는 #elifndef 지침을 어떤 숫자를 포함한다, 그러면 선택적으로 최대 하나의 #else 지시어를 포함하고 그리고 #endif 지시어와 함께 종료된다. 모든 내부 조건부 전처리 블럭은 별도(separately)로 처리된다.
각각의 #if, #ifdef, #ifndef, #elif, #elifdef, #elifndef(since C++23), and #else 지시어는 첫번째 #elif, #elifdef, #elifndef(since C++23), #else, #endif 지시어가 어떤 내부의 조건부 컴파일 블록에 귀속되지 않을때까지 코드 블럭을 제어한다.
#if, #ifdef 그리고 #ifndef 지시어는 지정된 조건에 테스트하고 그리고 만약에 정답이라 평가되면, 제어된 코드 블럭을 컴파일한다.
그런 경우 이후에 #else, #elifdef, #elifndef, 그리고 #elif 지시어는 무시된다. 그렇지 않으면 (Otherwise), 지정된 조건이 거짓으로 평가되면, 그 제어 코드 블록은 스킵되거나 이후에 #else, #elifdef, #elifndef 또는 #elif 지시어에 처리된다. 만약 그 이후 지시어가 #else라면, #else 지시어에 의해 제어되는 코드블록은 무조건 컴파일된다. 그렇지 않으면, #elif, #elifdef, 또는 #elifndef 지시어가 조건에 대해 확인하는 #if 지시어 인것 처럼(as if) 작동(acts)한다, 결과에따라 제어 코드 블록을 컴파일 또는 건너뛰고, 그리고 후자의 경우 후속 #elif, #elifdef, #elifndef 그리고 #else 지시어를 처리한다. 조건부 블록은 #eddif 지시어에 종료된다.
Condition evaluation
#if, #elif
표현식에는 정의된 식별자 또는 정의된 형식안에 단항 연산자를 포함한다. 식별자가 매크로 이름으로 정의되면 결과는 1이고, 그렇지 않으면 그 결과는 0이다.
표현식 또한 다음 표현을 따라 포함한다.
__has_include 표현식, 헤더 또는 소스파일이 존재하는지 감지한다.
__has_cpp_attribute 표현식, 주어진 속성 토큰이 지원되는지 그리고 지원되는 버전을 감지한다.
__has_embed 표현식, 리소스를 내장할 수 있는지 감지한다.
위에 언급된(mentioned above) 식별자는 이 컨텍스트에서 정의된 매크로 이름인것 처럼 처리된다.
이후 모든 매크로 표현 그리고 평가 정의 그리고 설명된 표현식이 끝나면, boolean 리터럴이 아닌 어떤 식별자는 0으로 대체된다.
그러면 표현식은 정수 상수 표현식으로 평가된다.
만약 그 표현식이 0이 아닌 값으로 평가되면, 그 제어 코드 블록은 포함되고 그렇지 않으면 건너뛴다.
#define ABCD 2
#include <iostream>
int main()
{
#ifdef ABCD
std::cout << "1: yes\n";
#else
std::cout << "1: no\n";
#endif
#ifndef ABCD
std::cout << "2: no1\n";
#elif ABCD == 2
std::cout << "2: yes\n";
#else
std::cout << "2: no2\n";
#endif
#if !defined(DCBA) && (ABCD < 2*4-3)
std::cout << "3: yes\n";
#endif
// Note that if a compiler does not support C++23's #elifdef/#elifndef
// directives then the "unexpected" block (see below) will be selected.
#ifdef CPU
std::cout << "4: no1\n";
#elifdef GPU
std::cout << "4: no2\n";
#elifndef RAM
std::cout << "4: yes\n"; // expected block
#else
std::cout << "4: no!\n"; // unexpectedly selects this block by skipping
// unknown directives and "jumping" directly
// from "#ifdef CPU" to this "#else" block
#endif
// To fix the problem above we may conditionally define the
// macro ELIFDEF_SUPPORTED only if the C++23 directives
// #elifdef/#elifndef are supported.
#if 0
#elifndef UNDEFINED_MACRO
#define ELIFDEF_SUPPORTED
#else
#endif
#ifdef ELIFDEF_SUPPORTED
#ifdef CPU
std::cout << "4: no1\n";
#elifdef GPU
std::cout << "4: no2\n";
#elifndef RAM
std::cout << "4: yes\n"; // expected block
#else
std::cout << "4: no3\n";
#endif
#else // when #elifdef unsupported use old verbose “#elif defined”
#ifdef CPU
std::cout << "4: no1\n";
#elif defined GPU
std::cout << "4: no2\n";
#elif !defined RAM
std::cout << "4: yes\n"; // expected block
#else
std::cout << "4: no3\n";
#endif
#endif
}
결과값
1: yes
2: yes
3: yes
4: no!
4: yes
#if 전처리로 뭘 하면 좋을까 고민 해봤다.
전처리가 빌드 하기전에 처리를 하는거니깐
만약에 게임 서버 코드에서 운영체제에 따라서 코드가 달라진다고 했을때
전처리로 나눠서 하면 되지 않을까 했는데..?
이미 존재했다.
#define _WIN32 or 64 일케 이미 운영체제별로 만들어 놓으셨음.
#define __APPLE__ <= 이건 맥
그래서 만약에 운영체제별로 코드를 나눠야 한다? 면 다음과 같이 쓰면 될거 같다.
#include <iostream>
int main() {
#if defined(_WIN32)
std::cout << "_WIN32 defined\n";
#endif
#if defined(_WIN64)
std::cout << "_WIN64 defined\n";
#endif
#if defined(__APPLE__)
std::cout << "__APPLE__ defined\n";
#endif
#if defined(__linux__)
std::cout << "__linux__ defined\n";
#endif
}
'C++' 카테고리의 다른 글
| 1. Preprocessor (C++) (0) | 2025.11.21 |
|---|