この奇妙なマクロコードに出会ったのは/usr/include/linux/kernel.h
:
/* Force a compilation error if condition is true, but also produce a
result (of value 0 and type size_t), so the expression can be used
e.g. in a structure initializer (or where-ever else comma expressions
aren't permitted). */
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
何:-!!
をするのですか?
更新:最近、マクロは/usr/include/linux/build_bug.h
ベストアンサー1
これは実際には、式 e が 0 に評価できるかどうかを確認し、評価できない場合はビルドを失敗させる方法です。
BUILD_BUG_OR_ZERO
このマクロの名前は少々間違っています。ではなく のような名前にすべきです...ON_ZERO
。(これは紛らわしい名前であるかどうかについての議論が時々ある。
この表現は次のように読みます。
sizeof(struct { int: -!!(e); }))
(e)
: 式を計算しますe
。!!(e)
: 論理的に 2 回否定します:0
ife == 0
; else1
。-!!(e)
: ステップ 2 の式を数値的に否定します。0
の場合0
、 、それ以外の場合は-1
。struct{int: -!!(0);} --> struct{int: 0;}
: ゼロの場合は、幅がゼロの匿名整数ビットフィールドを持つ構造体を宣言します。すべて問題なく、通常どおり続行されます。struct{int: -!!(1);} --> struct{int: -1;}
: 一方、ゼロでない場合は、負の数になります。負の幅を持つビットフィールドを宣言すると、コンパイル エラーになります。
したがって、構造体の幅が 0 のビットフィールド (これは問題ありません) または負の幅のビットフィールド (これはコンパイル エラーです) のいずれかになります。次に、sizeof
そのフィールドを取得して、適切な幅の を取得しますsize_t
( がゼロの場合は 0 になりますe
)。
何人かの人はこう尋ねました:なぜ を使わないのですかassert
?
keithmo の回答ここに良い回答があります:
これらのマクロはコンパイル時のテストを実装しますが、assert() は実行時のテストです。
まさにその通りです。実行時にカーネルの問題を検出したくはありません。カーネルはオペレーティング システムの重要な部分です。コンパイル時に問題を検出できれば、その分だけ良いのです。