순수 표준 C에서 컴파일 타임 어설 션이 가능하며 약간의 전처리 기교가 사용 시간을 assert()
처럼 깨끗하게 표시합니다.
핵심 요령은 컴파일 타임에 평가할 수 있고 일부 값에 오류가 발생할 수있는 구문을 찾는 것입니다. 하나의 대답은 배열의 선언이 음수 크기를 가질 수 없다는 것입니다. typedef를 사용하면 성공시 공간 할당을 방지하고 실패시 오류를 보존합니다.
오류 메시지 자체는 암호문이 음수 인 선언 (GCC는 "배열의 크기가 음수 임)"을 암시 적으로 나타낼 것이므로이 오류가 실제로 어설 션 검사임을 암시하는 배열 유형의 이름을 선택해야합니다 .
더 많은 문제는 컴파일 단위에서 한 번만 typedef
특정 유형 이름이 가능하다는 것입니다. 따라서 매크로는 선언 할 고유 한 형식 이름을 얻기 위해 각 용도별로 정렬해야합니다.
내 일반적인 해결책은 매크로에 두 개의 매개 변수가 필요하다는 것입니다. 첫 번째는 어설 션 조건이 true이고 두 번째 조건이 장면 뒤에 선언 된 유형 이름의 일부입니다. 플 린스에 의한 대답은 토큰 붙여 넣기와 여분의 인수가 필요없는 고유 한 이름을 형성하기 위해 미리 정의 된 매크로를 사용함을 암시합니다.
불행히도, 어설 션 확인이 포함 된 파일에 있으면 두 번째 포함 파일의 동일한 줄 번호 나 주 원본 파일의 해당 줄 번호와 충돌 할 수 있습니다. 매크로 __FILE__
을 사용하여이를 처리 할 수 있지만 문자열 상수로 정의되며 문자열 상수를 식별자 이름의 일부로 되돌릴 수있는 전 처리기 트릭이 없습니다. 합법적 인 파일 이름에는 식별자의 합법적 인 부분이 아닌 문자가 포함될 수 있습니다. 일반적인 사용은 같은 수 있습니다
/** A compile time assertion check.
*
* Validate at compile time that the predicate is true without
* generating code. This can be used at any point in a source file
* where typedef is legal.
*
* On success, compilation proceeds normally.
*
* On failure, attempts to typedef an array type of negative size. The
* offending line will look like
* typedef assertion_failed_file_h_42[-1]
* where file is the content of the second parameter which should
* typically be related in some obvious way to the containing file
* name, 42 is the line number in the file on which the assertion
* appears, and -1 is the result of a calculation based on the
* predicate failing.
*
* \param predicate The predicate to test. It must evaluate to
* something that can be coerced to a normal C boolean.
*
* \param file A sequence of legal identifier characters that should
* uniquely identify the source file in which this condition appears.
*/
#define CASSERT(predicate, file) _impl_CASSERT_LINE(predicate,__LINE__,file)
#define _impl_PASTE(a,b) a##b
#define _impl_CASSERT_LINE(predicate, line, file) \
typedef char _impl_PASTE(assertion_failed_##file##_,line)[2*!!(predicate)-1];
:
그래서, 다음의 코드 제안 할
$ gcc -c demo.c
demo.c:32: error: size of array `assertion_failed_demo_c_32' is negative
$
: GCC에서
#include "CAssert.h"
...
struct foo {
... /* 76 bytes of members */
};
CASSERT(sizeof(struct foo) == 76, demo_c);
을 어설 션 오류는 같을 것이다
나는 C로 정적 어설 션을 생성하는 것이 가능하다고 생각하지 않는다. –
몇 가지 좋은 답변과 중복 : http://stackoverflow.com/questions/174356/ways-to-assert-expressions-at-build-time-in-c –
이 질문은 상대적으로 오래되었으므로 : _Static_assert'와 관련 'static_assert' 매크로는 C11에서 표준화되었습니다. 이것은 현재 언어에 내장되어 있습니다. – Leushenko