アークピットのホームページに戻る

WinAPIトピックのトップページに戻る

APIトピックの各章に移動する

ダウンロードのページに移動する
ダウンロードができ
ない場合の対処法
 

ページ移動

1-4-1. 構造体メンバのバイト位置を知る方法

 MFCのソースを必死に解読していた時に、offsetofというマクロを見つけました。これは以下の様に定義されています。
#define offsetof(s,m) (size_t)&(((s *)0)->m) //stddef.hで定義
 最初これを見て、何のことだろうと思いました。仕様書を見ると、sは構造体の名前、mはその構造体のメンバ変数の名前だそうです。
	(s *)0
 普通は何かをポインタでキャストするときは、それはポインタの変数か、変数の&(アドレス)です。ここではそれが0(ゼロ)になっています。考えてみると、普通はポインタ変数ですが、絶対アドレスでも間違いではありません。sは構造体名ですので、その構造体はアドレス0に置かれた状態にあります。
	((s *)0)->m
そしてこれで、構造体のメンバを示します。
	&(((s *)0)->m)
 &でそのメンバのアドレスを差します。構造体はアドレス0に置かれています。つまり構造体の最初のメンバは、0番地で、0を返し、指定されたメンバもそれぞれの構造体での相対位置を差すことになります。最後に&はポインタなので、size_tでキャストして、サイズに変換しています。16ビットのC言語ではポインタは32ビット(Lモデル)で、size_tはunsigned intで16ビットですので、この様な変換が必要です。

 最初なんでこのマクロに疑問をもったかと言うと、アドレス0にキャストした構造体のメンバをアクセスすると、勘違いしたからです。OS管理外のメモリアクセスは、16ビットの8086系では重要なトラブルにはなりませんが、32ビットOSや68000では、たとえリードでもメモリのアクセス違反になりストップします。しかしこのマクロでは、メンバ変数を読むのではなく、&でアドレス計算しているだけです。それで問題なく動作すると言うわけです。

ページ移動