常见的初始序列和对齐

dyp*_*dyp 13 c++ memory-alignment unions standard-layout c++11

在考虑这个问题的反例时,我提出了:

struct A
{
    alignas(2) char byte;
};
Run Code Online (Sandbox Code Playgroud)

但如果这是合法的和标准的布局,它是否与布局兼容struct B

struct B
{
    char byte;
};
Run Code Online (Sandbox Code Playgroud)

此外,如果我们有

struct A
{
    alignas(2) char x;
    alignas(4) char y;
};
// possible alignment, - is padding
// 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
//  x  -  -  -  y  -  -  -  x  -  -  -  y  -  -  -

struct B
{
    char x;
    char y;
}; // no padding required

union U
{
    A a;
    B b;
} u;
Run Code Online (Sandbox Code Playgroud)

是否有一个共同的初始序列AB?如果是这样,它是否包括A::y&B::y?也就是说,我们可以编写以下内容而无需调用UB吗?

u.a.y = 42;
std::cout << u.b.y;
Run Code Online (Sandbox Code Playgroud)

(C++ 1y /"fixed C++ 11"的答案也欢迎)


  • 有关对齐,请参见[basic.align],对齐对齐器请参见[dcl.align].

  • [basic.types]/11表示为基本类型"如果两种类型的T1T2具有相同的类型,则T1T2是布局兼容的类型." (一个基本问题是是否A::byteB::byte布局兼容的类型)

  • [class.mem]/16"如果两个标准布局结构类型具有相同数量的非静态数据成员,并且相应的非静态数据成员(按声明顺序)具有布局兼容类型,则它们是布局兼容的."

  • [class.mem]/18"如果相应的成员具有布局兼容类型且两个成员都不是位字段,或者两者都是具有相同宽度的位字段,则两个标准布局结构共享一个公共初始序列或更多初始成员."

  • [class.mem]/18"如果标准布局联合包含两个或多个共享公共初始序列的标准布局结构,并且标准布局联合对象当前包含这些标准布局结构中的一个,则允许检查其中任何一个的共同初始部分."

当然,在语言 - 律师层面,另一个问题是,对于共同的初始序列的检查是"允许的"是什么意思.我想其他段落可能会产生上述u.b.x未定义的行为(从未初始化的对象中读取).

小智 0

\n

(一个根本问题是 A::byte 和 B::byte 是否具有布局兼容的类型)

\n
\n\n

是的。这是最重要的部分。alignas- 属性属于声明的实体,而不是类型。可以通过std::is_same和轻松测试decltype

\n\n
\n

即,我们可以编写以下代码而不调用 UB 吗?

\n
\n\n

因此这不是UB,相关段落已被您引用。

\n\n

编辑:请原谅,这当然会导致 UB,因为成员之间的填充未(或实现)定义(\xc2\xa79.2/13)!我不小心误读了这个例子,因为我认为它访问的是 x 而不是 y,因为对于 x 它实际上总是有效的 - 而对于 y 理论上它不需要(尽管实际上总是会)。

\n