私をからかっている本のどこかで sizeof 演算子のこの複雑な宣言を見ました:
#define SIZEOF(int) (int)&((int *)0)[1]
ここで何が起こっているのか、この宣言を説明できる人はいますか...?
私をからかっている本のどこかで sizeof 演算子のこの複雑な宣言を見ました:
#define SIZEOF(int) (int)&((int *)0)[1]
ここで何が起こっているのか、この宣言を説明できる人はいますか...?
これは、[1]「展開」された部分です。
(int)(&(*(((int*)0) + 1)))
どのように機能するかわかりましたか?
sizeof intポインタ演算のプロパティにより0 が増加し、最終的なintキャストによって、結果のアドレスの値である「サイズ」が取得されます。
ただし、これはまったく未定義の動作 (null の演算と、無効なポインターの逆参照の可能性) であり、かなり無意味です。
マクロ パラメータによる更新はあまり意味がありません。最終的なキャストはおそらくstd::uintptr_t.
まず、この用語は混乱を招きますint。おなじみの型のキーワードであると当然想定しますが、この場合はそうではなく、マクロの引数です。簡単にするために、マクロを次のように考えます。
#define SIZEOF(type) &((type *)0)[1]
このように見ると、マクロが最初にアドレス 0 を へのポインターにキャストしtype、次に 2 番目の要素のアドレスを取得していることがわかります。これで大きさがわかります。
SIZEOF整数のサイズとして定義します。
(int *)0アドレス 0 の int ポインタ[1]その次の整数にアクセスします。(int *)0アドレスがゼロであるため、次のアドレスは前のアドレスの直後sizeof intにあるためです。(int)サイズはポインタではなく数値であるため、数値にキャストします。明らかに、これは厄介なハックです。単純に を使用する必要がありますsizeof int。