Godbolt を使用して、次の構造体のレイアウト情報を見ています。
struct Foo1 {
int size;
void *data[];
};
struct Foo2 {
int size;
struct {
void *data[];
};
};
両方の構造体のレイアウトが同じであるFoo1
と予想していFoo2
ました。私が理解していることから、匿名のネストされた構造体のフィールドは、単に親構造体に「折りたたまれ」ます。したがって、 のレイアウトは のレイアウトとFoo2
同じになるはずですFoo1
。
ただし、MSVC 19.16 によって生成され、フラグを使用したときに表示されるレイアウトは/d1reportSingleClassLayoutFoo
異なります。
class Foo1 size(8):
+---
0 | size
| <alignment member> (size=4)
8 | data
+---
class Foo2 size(16):
+---
0 | size
| <alignment member> (size=4)
| <anonymous-tag> <alignment member> (size=8)
8 | data
| <alignment member> (size=7)
+---
Foo2
の倍の大きさですFoo1
。そしてdata
突然、1バイトのサイズがあるようです。
で生成されるいくつかの警告があります-Wall
:
warning C4200: nonstandard extension used: zero-sized array in struct/union
note: This member will be ignored by a defaulted constructor or copy/move assignment operator
warning C4820: 'Foo1': '4' bytes padding added after data member 'Foo1::size'
warning C4200: nonstandard extension used: zero-sized array in struct/union
note: This member will be ignored by a defaulted constructor or copy/move assignment operator
warning C4820: 'Foo2::<anonymous-tag>': '7' bytes padding added after data member 'Foo2::data'
warning C4201: nonstandard extension used: nameless struct/union
warning C4820: 'Foo2': '4' bytes padding added after data member 'Foo2::size'
しかし、これらのいずれも、レイアウトの違いを説明したり、未定義の動作を示唆したりするようには見えません。そして、ドキュメント: Anonymous structsもそうではありません。
記録として、このコードが MSVC 拡張機能に依存していることは知っています。
warning C4200: nonstandard extension used: zero-sized array in struct/union
warning C4201: nonstandard extension used: nameless struct/union
「サイズがゼロの配列」は、フィールドの前に配置するとエラーがスローdata
されるため、柔軟な配列メンバーのようです。size
Foo1
とのレイアウトがFoo2
異なるのはなぜですか?