プログラミング言語Cにおいて、式(expression)として扱えるコンパイル時アサートの実装例(C99以降)。*1 *2
#include <assert.h> #define static_assert_expr(cexp_, msg_) \ ((void)sizeof(struct { \ static_assert(cexp_, msg_); \ int dummy_member; \ }))
C言語では空の構造体が禁止される(→id:yohhoy:20230430)ため、ダミーのメンバdummy_memberを追加している。C11 6.2.5/p20, 6.7.2.1/p1, 6.7.10/p1より一部引用(下線部は強調)。
Any number of derived types can be constructed from the object and function types, as follows:
- (snip)
- A structure type describes a sequentially allocated nonempty set of member objects (and, in certain circumstances, an incomplete array), each of which has an optionally specified name and possibly distinct type.
- (snip)
Syntax
struct-or-union-specifier:
struct-or-union identifieropt{struct-declaration-list}
struct-or-union identifier
struct-or-union:
struct
union
struct-declaration-list:
struct-declaration
struct-declaration-list struct-declaration
struct-declaration:
declaration-specifiers init-declarator-listopt;
static_assert-declaration
(snip)
Syntax
static_assert-declaration:
_Static_assert(constant-expression,string-literal);
ノート:C++ではsizeof式での新しい型定義は明示的に禁止されている。*3
関連URL
- (PDF) N3313 New elementsof() operator (v2)
- gcc - Static assert in C - Stack Overflow
- https://x.com/yohhoy/status/1828436457855557786
*1:C11で導入された _Static_assert/static_assert は構文要素上は宣言(declaration)に区分されるため、そのままでは式(expression)の一部として利用できない。C17時点では<assert.h>ヘッダによる static_assert マクロ定義を必要とするが、C23現在は static_assert がキーワードに格上げされ、従前の _Static_assert 利用は非推奨となっている。
*2:C99時点ではLinuxの BUILD_BUG_ON マクロのように、負の要素数を持つ配列型によるHACK実装が行われていた。実装例:((void)sizeof(char[(cexpr_)?1:-1]))
*3:C++03 5.3.3/p5: "Types shall not be defined in a sizeof expression."