1. ホーム
  2. c

[解決済み] C言語のコードで「:-!」とは何ですか?

2022-03-16 20:18:03

質問

の中で、この奇妙なマクロコードにぶつかった。 /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); }))

とは何ですか? :-!! を行うか?

どのように解決するのですか?

これは、実質的には 式eが0と評価できるかどうかをチェックし、評価できない場合はビルドを失敗させる方法です。 .

このマクロはやや名前が間違っています。 BUILD_BUG_OR_ZERO よりも、むしろ ...ON_ZERO . (これまでにも という名称は紛らわしいのではないか、という議論が時折なされています。 .)

このように式を読む必要があります。

sizeof(struct { int: -!!(e); }))

  1. (e) : 計算式 e .

  2. !!(e) : 論理的に2回否定する。 0 もし e == 0 そうでない場合は 1 .

  3. -!!(e) : 手順 2 の式を数値で否定する。 0 であった場合 0 そうでない場合は -1 .

  4. struct{int: -!!(0);} --> struct{int: 0;} : 0であった場合、幅が0の匿名整数ビットフィールドを持つ構造体を宣言します。すべてうまくいき、通常通りに進みます。

  5. struct{int: -!!(1);} --> struct{int: -1;} : 一方、もしそれが ではない ゼロであれば、何らかの負数になります。任意のビットフィールドを ネガティブ の幅はコンパイルエラーになります。

つまり、構造体の幅が 0 のビットフィールドは問題ありませんが、負の幅のビットフィールドはコンパイル エラーになります。そこで sizeof そのフィールドを取得するため size_t を適切な幅で指定します (この幅は e がゼロの場合)。


という質問もありました。 を使うだけではダメなのでしょうか? assert ?

keithmoの回答 が良い回答をしています。

これらのマクロはコンパイル時のテストを実装しており、assert()は実行時のテストです。

まさにその通りです。の問題を検出したいとは思わないでしょう。 カーネル もっと早く発見できたはずのものを、実行時に発見してしまうのです。これはオペレーティングシステムの重要な部分です。コンパイル時に問題を検出できるのであれば、それに越したことはありません。