32

c/c++ の場合 (この点に関しては同じであると想定しています)、次の場合:

struct S {
  T a;
  .
  .
  .
} s;

以下は真であることが保証されていますか?

(void*)&s == (void*)&s.a;

言い換えれば、最初のメンバーの前にパディングがないという保証はありますか?

4

2 に答える 2

45

C では、はい、同じアドレスです。シンプルでわかりやすい。


C++ では、いいえ、それらは同じアドレスではありません。基本クラスはすべてのメンバーの前に置くことができます (そして私は疑っています)。仮想メンバー関数は通常、隠しデータを構造体のどこかに追加します。さらにややこしいことに、C++ コンパイラは、クラスが標準レイアウト タイプでない限り、メンバーを自由に再配置することもできます (ただし、どのコンパイラもそうするかどうかはわかりません)。

最後に、C++ 構造体が標準レイアウト型で構成され、基本クラスも仮想関数も含まず、すべてのメンバーが同じ可視性を持ち、忘れていた他の制限がある可能性がある場合 C ルールにフォールバックし、最初のメンバーがオブジェクト自体と同じアドレスになります。

§ 9.2/7

標準レイアウト クラスは、次のようなクラスです。
— 非標準レイアウト クラス (またはそのような型の配列) または参照の非静的データ メンバーを
持たない — 仮想関数 (10.3) も仮想基底クラス ( 10.1)、
— すべての非静的データ メンバーに対して同じアクセス制御 (条項 11) を
持っている — 非標準レイアウトの基本クラス
を持たない — 最も派生したクラスに非静的データ メンバーを持たず、多くても 1 つしか持たない非静的データ メンバーを持つ基本クラス、または非静的データ メンバーを
持つ基本クラスがなく、かつ — 最初の非静的データ メンバーと同じ型の基本クラスがない。

§ 9.2/20

reinterpret_cast を使用して適切に変換された標準レイアウトの構造体オブジェクトへのポインターは、その最初のメンバー (または、そのメンバーがビットフィールドの場合は、それが存在するユニット) を指し、その逆も同様です。[ 注: したがって、標準レイアウトの構造体オブジェクト内に名前のないパディングがある場合がありますが、適切な配置を実現するために必要なため、先頭にはありません。—終わりのメモ]

于 2013-07-24T21:30:20.287 に答える
16

はい、そうです。

C および C++ (POD の場合) では、最初の構造体メンバーの前にパディングがないことが保証されています。

Cの引用:

(C11、6.7.2.1p15) 「構造オブジェクト内に名前のないパディングがある場合がありますが、先頭にはありません。」

C++ の引用:

(C++11、9.2p20) 「したがって、適切な位置合わせを実現するために必要に応じて、標準レイアウトの構造体オブジェクト内に名前のないパディングがある可能性がありますが、先頭にはありません」

于 2013-07-24T21:28:39.293 に答える