私をからかっている本のどこかで 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
。