c++ - POD 结构或标准布局类型的成员是否保证根据其对齐要求对齐?

标签 c++ c++11 language-lawyer memory-alignment c++03

给定一个 POD 结构(在 C++03 中)或标准布局类型(在 C++11 中),所有成员都有基本对齐要求,是否保证每个成员都按照它的对齐要求?

换句话说,对于标准布局类型 Sm0 ... mn } 中的所有成员 m_k,

  struct S {
    T0 m0;
    T1 m1;
    ...
    TN mn;
  };

是否保证以下表达式的计算结果为 true

  (offsetof(S,m_k) % alignof(decltype(S::m_k))) == 0

请给出 C++03 和 C++11 的答案并引用标准的相关部分。来自 C 标准的支持证据也会有所帮助。


我对 C++03 标准 (ISO/IEC 14882:2003(E)) 的解读是,除了第一个成员外,它对 POD 结构中成员的对齐保持沉默。相关段落是:

在规范的语言中,对象是一个“存储区域”:

1.8 The C + + object model [intro.object]

1.8/1 The constructs in a C + + program create, destroy, refer to, access, and manipulate objects. An object is a region of storage. ...

对象根据对齐要求进行分配:

3.9 Types [basic.types]

3.9/5 Object types have alignment requirements (3.9.1, 3.9.2). The alignment of a complete object type is an implementation-defined integer value representing a number of bytes; an object is allocated at an address that meets the alignment requirements of its object type.

基本类型有对齐要求:

3.9.1 Fundamental types [basic.fundamental]

3.9.1/3 For each of the signed integer types, there exists a corresponding (but different) unsigned integer type: "unsigned char", "unsigned short int", "unsigned int", and "unsigned long int," each of which occupies the same amount of storage and has the same alignment requirements (3.9) as the corresponding signed integer type;...

填充可能由于“实现对齐要求”而发生:

9.2 Class members [class.mem]

9.2/12 Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).

9.2/12 中的“已分配”一词是否与 3.9/5 中的“已分配”具有相同的含义?规范中“已分配”的大多数用法是指动态存储分配,而不是结构内部布局。在 9.2/12 中使用 may 似乎暗示 3.9/5 和 3.9.1/3 的对齐要求可能对结构成员没有严格要求。

POD-struct 的第一个成员将根据结构的对齐要求进行对齐:

9.2/17 A pointer to a POD-struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa. [Note: There might therefore be unnamed padding within a POD-struct object, but not at its beginning, as necessary to achieve appropriate alignment. ]

[在上述所有引号中都添加了重点。]

最佳答案

POD 结构的每个元素本身就是一个对象,并且只能根据这些对象的对齐要求来分配对象。但是,对齐要求可能会发生变化,因为某些东西是另一个对象的子对象 ([basic.align]/1, 2:

1 Object types have alignment requirements (3.9.1, 3.9.2) which place restrictions on the addresses at which an object of that type may be allocated. An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated. An object type imposes an alignment requirement on every object of that type; stricter alignment can be requested using the alignment specifier (7.6.2).

2 A fundamental alignment is represented by an alignment less than or equal to the greatest alignment supported by the implementation in all contexts, which is equal to alignof(std::max_align_t) (18.2). The alignment required for a type might be different when it is used as the type of a complete object and when it is used as the type of a subobject. [Example:

struct B { long double d; };
struct D : virtual B { char c; }

When D is the type of a complete object, it will have a subobject of type B, so it must be aligned appropriately for a long double. If D appears as a subobject of another object that also has B as a virtual base class, the B subobject might be part of a different subobject, reducing the alignment requirements on the D subobject.—end example ] The result of the alignof operator reflects the alignment requirement of the type in the complete-object case.

[强调添加]

虽然这些示例通过继承引用子对象,但规范性措辞只是泛指子对象,所以我相信同样的规则适用,所以一方面你可以假设每个子对象都对齐,以便可以访问它。另一方面,不,你不能一定假设这将是 alignof 给你的相同对齐方式。

[引用来自 N4296,但我相信这同样适用于所有最新版本。当然,C++98/03 根本没有 alignof,但我相信同样的基本原则也适用——成员将对齐以便它们可以使用,但对齐要求是'不一定与它们用作独立对象时相同。]

关于c++ - POD 结构或标准布局类型的成员是否保证根据其对齐要求对齐?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32700032/

相关文章:

c++ - 在 C++ 中正确模板化字符串比较器

c++ - OwnerDraw CButton mfc 焦点

c++ - 声明中 noexcept 不一致是否违反 ODR?

c++ - 如何使用不同的构造函数从堆栈实例化一个类?

c++11 - 以下 C++11 代码应该如何工作?

c - `printf("%.-1s\n", "foo")` 会调用未定义的行为吗?

uint8_t 可以是非字符类型吗?

c++ - 如何在 Linux 架构上即时列出 C 代码中可用的所有函数/符号?

C++ - STL vector 问题

c++ - 实现 std::hash<T> 时修改内部结构