C 전처리 기가 열거 형 값을 같은 것으로 간주하는 이유는 무엇입니까?
왜 않는 std::cout
다음 코드 줄은 비록 실행 A
과 B
다른가?
#include <iostream>
enum T { A = 1, B = 2 };
// #define A 1
// #define B 2
int main() {
#if (A == B)
std::cout << A << B;
#endif
}
#define
대신 (주석 처리됨) 사용하면 예상대로 출력이 표시되지 않습니다.
질문 이유 :
맨 위에있는 줄에 주석을 달거나 주석을 제거하여 쉽게 모드를 변경할 수있는 일부 테스트 코드에 대한 모드 선택기를 갖고 싶습니다.
enum T { MODE_RGB = 1, MODE_GREY = 2, MODE_CMYK = 3 };
// #define MODE MODE_RGB
#define MODE MODE_GREY
// #define MODE MODE_CMYK
int main() {
#if (MODE == MODE_RGB)
// do RGB stuff
#elif (MODE == MODE_GREY)
// do greyscale stuff
#else
// do CMYK stuff
#endif
// some common code
some_function(arg1, arg2,
#if (MODE == MODE_RGB)
// RGB calculation for arg3,
#elif (MODE == MODE_GREY)
// greyscale calculation for arg3,
#else
// CMYK calculation for arg3,
#endif
arg4, arg5);
}
예를 들어 숫자 값을 사용할 수 있다는 것을 알고 있습니다.
#define MODE 1 // RGB
...
#if (MODE == 1) // RGB
하지만 코드를 읽기 어렵게 만듭니다.
이것에 대한 우아한 해결책이 있습니까?
어떤 매크로가 호출되지 있습니다 A
또는 B
, 그래서 당신에 #if
선 A
및 B
대체 얻을 0
당신이 실제로 그래서, :
enum T { A = 1, B = 2 };
int main() {
#if (0 == 0)
std::cout << A << B;
#endif
}
컴파일러가 enum
. 전처리 기는 매크로 ( #define
) 에 대해서만 알고 있습니다.
이는 전처리 기가 컴파일 시간 전에 작동하기 때문입니다.
열거 형 정의가 컴파일 타임에 발생하기 때문에 A와 B는 모두 빈 (pp-number 0
) 으로 정의되어 전처리 시간에 동일하므로 출력 문이 컴파일 된 코드에 포함됩니다.
사용하면 #define
사전 처리 시간에 다르게 정의되므로 명령문이 false로 평가됩니다.
원하는 작업에 대한 의견과 관련하여 전처리기를 사용하지 않아도됩니다 #if
. 및 (또는 또는 ) 모두 여전히 정의 if
되어 있으므로 표준 을 사용할 수 있습니다 .MODE
MODE_GREY
MODE_RGB
MODE_CMYK
#include <iostream>
enum T { MODE_RGB = 1, MODE_GREY = 2, MODE_CMYK = 3 };
#define MODE MODE_GREY
int main()
{
if( MODE == MODE_GREY )
std::cout << "Grey mode" << std::endl;
else if( MODE == MODE_RGB )
std::cout << "RGB mode" << std::endl;
else if( MODE == MODE_CMYK )
std::cout << "CMYK mode" << std::endl;
return 0;
}
전처리기만 사용하는 다른 옵션은 @TripeHound 가 아래에 올바르게 대답 했으므로이를 수행하는 것 입니다.
Identifiers that are not defined macros are interpreted as value 0 in conditional preprocessor directives. Therefore, since you hadn't defined macros A
and B
, they are both considered 0 and two 0 are equal to each other.
The reason why undefined (to the pre-processor) identifiers are considered 0 is because it allows using undefined macros in the conditional without using #ifdef
.
The preprocessor runs before the compiler, which means that the preprocessor doesn't know anything about symbols defined by the compiler and therefore it can't act depending on them.
As the other answers said, the C preprocessor doesn't see enums. It expects, and can only understand, macros.
Per the C99 standard, §6.10.1 (Conditional inclusion):
After all replacements due to macro expansion and the defined unary operator have been performed, all remaining identifiers are replaced with the pp-number 0
In other words, in an #if or #elif directive, any macros that cannot be expanded, because they don't exist/are undefined, will behave exactly as if they'd been defined as 0, and therefore will always be equal to each other.
You can catch likely unintended behavior like this in GCC/clang with the warning option -Wundef (you'll probably want to make it fatal with -Werror=undef).
Other answers explain why what you're trying doesn't work; for an alternative, I'd probably go with:
#define RGB 1
#define GREY 2
#define CMYK 3
#define MODE RGB
#if MODE == RGB
//RGB-mode code
#elif MODE == GREY
//Greyscale code
#elif MODE == CMYK
//CMYK code
#else
# error Undefined MODE
#endif
You might want prefixes on the RGB/GREY/CMYK if there's a danger of clashes with "real" source code.
The posts have explained why, but a possible solution for you that keeps readability might be like this
#define MODE_RGB
int main()
{
#ifdef MODE_RGB
std::cout << "RGB mode" << std::endl;
#elif defined MODE_GREY
std::cout << "Grey mode" << std::endl;
#elif defined MODE_CMYK
std::cout << "CMYK mode" << std::endl;
#endif
}
You just then need to change the macro at the top, to only the macro you are interested in is defined. You could also include a check to make sure that one and only one is defined and if not then and do #error "You must define MODE_RGB, MODE_GREY or MODE_CMYK
'program tip' 카테고리의 다른 글
Environment.TickCount 대 DateTime.Now (0) | 2020.11.29 |
---|---|
UINavigationBar iOS 7 아래에보기가 숨겨 짐 (0) | 2020.11.29 |
전체 URL을 사용할 때 PHP file_get_contents 매우 느림 (0) | 2020.11.29 |
IE11 문서 모드를 기본으로 가장자리로 설정하는 방법은 무엇입니까? (0) | 2020.11.28 |
디버깅 중 Visual Studio : 함수를 평가하려면 모든 스레드를 실행해야합니다. (0) | 2020.11.28 |