yohhoyの日記

技術的メモをしていきたい日記

式static_assert in C言語

プログラミング言語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

*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."