offsetof
| ヘッダ <cstddef> で定義 |
||
| #define offsetof(type, member) /* 実装定義 */ |
||
マクロ offsetof は、指定された型のオブジェクトの先頭から指定されたサブオブジェクトまでのオフセット(バイト単位)を、パディングビットを含む場合も含む整数定数式 std::size_t に展開します。
静的記憶域期間を持つ type 型のオブジェクト o が与えられた場合、 o.member は o のサブオブジェクトを参照する左辺値定数式でなければなりません。それ以外の場合は、動作は未定義です。特に、member が 静的データメンバ、ビットフィールド、または メンバ関数 の場合、動作は未定義です。
type が PODType(C++11まで) ではなく、標準レイアウト型(C++11以降) の場合、offsetof の結果は未定義(C++17まで)、offsetof マクロの使用は条件付きでサポートされます(C++17以降)。
式 offsetof(type, member) は決して 型依存 ではなく、type が依存である場合にのみ値依存です。
目次 |
[編集] 例外
offsetof は例外をスローしません。
|
式 noexcept(offsetof(type, member)) は常に true に評価されます。 |
(C++11以降) |
[編集] ノート
|
標準レイアウト型の最初のメンバのオフセットは常にゼロです(空基底クラスの最適化は必須です)。 |
(C++11以降) |
offsetof は標準 C++ では実装できず、コンパイラのサポートが必要です:GCC、LLVM。
member は直接メンバに限定されません。メンバメンバの要素のような、与えられたメンバのサブオブジェクトを示すことができます。これは C DR 496 によって指定されています。
C23 では、`offsetof` で括弧で囲まれていないカンマを含む新しい型を定義することは未定義の動作であり、そのような使用は C++ モードの実装では一般的にサポートされていません。例: offsetof(struct Foo { int a, b; }, a) は、すべての既知の実装で拒否されます。
[編集] 例
#include <cstddef> #include <iostream> struct S { char m0; double m1; short m2; char m3; // private: int z; // warning: 'S' is a non-standard-layout type }; int main() { std::cout << "offset of char m0 = " << offsetof(S, m0) << '\n' << "offset of double m1 = " << offsetof(S, m1) << '\n' << "offset of short m2 = " << offsetof(S, m2) << '\n' << "offset of char m3 = " << offsetof(S, m3) << '\n'; }
実行結果の例
offset of char m0 = 0 offset of double m1 = 8 offset of short m2 = 16 offset of char m3 = 18
[編集] 不具合報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| CWG 273 | C++98 | 単項 `operator&` がオーバーロードされている場合、`offsetof` が機能しない可能性があります。 | 正しく機能することが要求されています。 `operator&` がオーバーロードされている場合でも。 |
| LWG 306 | C++98 | `type` が PODType でない場合の動作が指定されていませんでした。 | この場合、結果は未定義です。 |
| LWG 449 | C++98 | `offsetof` のその他の要件は LWG issue 306 の解決によって削除されました。 |
それらを元に戻しました。 |
[編集] 関連項目
| sizeof 演算子が返す符号無し整数型 (typedef) | |
| (C++11) |
型がスタンダードレイアウト型であるかをチェックする (クラステンプレート) |
| C ドキュメント(offsetof について)
| |