글쎄, 나는이 구문에 대한 대안이 언급되지 않았다는 것에 상당히 놀랐다. 또 다른 일반적인 (그러나 오래된) 메커니즘은 정의되지 않은 함수를 호출하고 어설 션이 올바른 경우 최적화 프로그램을 사용하여 함수 호출을 컴파일 아웃하는 것입니다.
#define MY_COMPILETIME_ASSERT(test) \
do { \
extern void you_did_something_bad(void); \
if (!(test)) \
you_did_something_bad(void); \
} while (0)
이 메커니즘이 작동하는 동안 (최적화를 사용하는 한) 링크 할 때까지 오류를보고하지 않는 단점이 있으며, 이때 you_did_something_bad () 함수에 대한 정의를 찾지 못합니다. 이것이 커널 개발자들이 음의 크기의 비트 필드 폭과 음의 크기의 배열 (나중에 GCC 4.4에서 빌드 중단을 중단 한)과 같은 트릭을 사용하기 시작한 이유입니다.
컴파일 타임 어설 션이 필요하다는 것에 동조하여 GCC 4.3 은이 오래된 개념을 확장 할 수 있는 error
기능 속성 을 도입 했지만 더 이상 비밀스러운 "네거티브 크기의 배열이 아닌"사용자가 선택한 메시지로 컴파일 타임 오류를 생성합니다. "오류 메시지!
#define MAKE_SURE_THIS_IS_FIVE(number) \
do { \
extern void this_isnt_five(void) __attribute__((error( \
"I asked for five and you gave me " #number))); \
if ((number) != 5) \
this_isnt_five(); \
} while (0)
실제로 Linux 3.9부터는 compiletime_assert
이 기능을 사용하는 매크로가 bug.h
있으며 대부분의 매크로가 그에 따라 업데이트되었습니다. 여전히이 매크로는 이니셜 라이저로 사용할 수 없습니다. 그러나 by 문 표현 (다른 GCC C- 확장)을 사용하면 가능합니다!
#define ANY_NUMBER_BUT_FIVE(number) \
({ \
typeof(number) n = (number); \
extern void this_number_is_five(void) __attribute__(( \
error("I told you not to give me a five!"))); \
if (n == 5) \
this_number_is_five(); \
n; \
})
이 매크로는 매개 변수를 정확히 한 번만 평가하고 (부작용이있는 경우) "나에게 5를주지 말라고 알려주는 컴파일 타임 오류"를 생성합니다. 식이 5로 평가되거나 컴파일 타임 상수가 아닌 경우
왜 우리는 음의 크기의 비트 필드 대신 이것을 사용하지 않습니까? 아아, 현재 명령문 표현식이 자체적으로 일정하더라도 (즉, 열거 상수, 비트 필드 너비 등) 상수 이니셜 라이저로 사용하는 것을 포함하여 명령문 표현식 사용에 대한 많은 제한이 있습니다. 컴파일 타임에 그렇지 않으면 __builtin_constant_p()
테스트를 통과합니다 ). 또한 기능 본체 외부에서는 사용할 수 없습니다.
다행스럽게도 GCC는 이러한 단점을 곧 수정하고 상수 명령문 표현식을 상수 이니셜 라이저로 사용할 수 있기를 바랍니다. 여기서 어려운 점은 올바른 상수 표현을 정의하는 언어 사양입니다. C ++ 11은이 유형 또는 사물에 대해서만 constexpr 키워드를 추가했지만 C11에는 대응하는 키워드가 없습니다. C11은이 문제의 일부를 해결하는 정적 어설 션을 얻었지만 이러한 단점을 모두 해결하지는 못합니다. 따라서 gcc가 -std = gnuc99 & -std = gnuc11 또는 그와 같은 일부를 통해 constexpr 기능을 확장 기능으로 사용할 수있게하고 명령문 표현 등에 사용할 수 있기를 바랍니다. 알.