arrow 若葉プログラミング塾 > 知識の玉手箱 > C関数リファレンス >
offsetof
offsetofマクロ

このマクロの目的

offsetof マクロは、構造体のメンバのバイト位置を示す整数を返す。

定義

	#include <stddef.h>
	offsetof(type, member-designator);

働き

このマクロは、 member-designatortype 型の先頭から何バイト目にあるかという size_t 型の整数定数に展開される。構造体メンバに対し、構造体の先頭からのバイト数になる。 member-designator は、

	static type t;

という宣言があった時、 &(t.member-designator) という表現がアドレス定数になるものでなければならない。 (指定されたメンバがビットフィールドであった場合の動作は未定義である。)

解説

実際の stddef.h 内には #define offsetof(s,m) (size_t)&(((s *)0)->m) というように定義されている場合が多い。 このマクロの使い方はいろいろ考えられるが、代表的なのは可変長構造体に必要な動的メモリのサイズを計算する時であろうか。

以下のサンプルの表示結果は、多くの32ビットOS用の処理系では "4" になると思われる。

#include <stdio.h>
#include <stddef.h>

struct st{
	size_t size;
	char str[1];
};

int main(void){
	printf("%u", (unsigned)offsetof(struct st, str));
	return 0;
}

また、この例で malloc(offsetof(struct st, str) + 20) とすると、返り値のポインタの先の構造体には str が20バイト分確保される。 これは struct hack と呼ばれることがある技法だが、規格では動作することは保証されていない。ただし、ほぼ確実に動作する。

ちなみに、以下のサンプルのようなトリッキーなことも可能だ。結果は多くの32ビットの場合 "11" になる。

#include <stdio.h>
#include <stddef.h>

struct outer{
	void *pad;
	struct inner{
		const char *s;
		char b[8];
	} in;
};

int main(void){
	printf("%u", (unsigned)offsetof(struct outer, in.b[3]));
	return 0;
}
arrow 若葉プログラミング塾 > 知識の玉手箱 > C関数リファレンス >
KC