提问人:The Floating Brain 提问时间:10/9/2023 最后编辑:SebastianThe Floating Brain 更新时间:11/9/2023 访问量:134
C++ 连续内存布局中的匿名联合
Anonymous Unions in C++ Contiguous Memory Layout
问:
struct Vec0
{
union { float x, r, h; };
union { float y, g, s; };
union { float z, b, v; };
};
我想问一下,C++ 标准是否保证此数据将与我编写的数据完全相同
struct Vec1
{
float x, y, z;
};
地址紧跟在地址加上 + 填充位/对齐的长度之后(我认为)。y
x
float
认为它确实(保证布局),但很好奇它是否由 ISO C++ 标准保证?
更新:
澄清一下,我对这个问题很感兴趣,ISO C++ 标准中是否有任何保证
offsetof(Vec0, x /*or r h*/) == offsetof(Vec1, x)
offsetof(Vec0, y /*or g s*/) == offsetof(Vec1, y)
offsetof(Vec0, z /*or b v*/) == offsetof(Vec1, z)
这可能属于布局兼容的类别
我还对 的偏移量是否感兴趣(但不一定是因为人们可能无法在 //etc 之外使用,也许除非在假设中它能够访问 //etc 之外的数据成员)如果它们的所有数据成员都成为 /,则每个数据成员在两者之间将是相同的。offsetof
offsetof
struct
class
private
protected
struct
class
private
protected
另外,请注意,这不是软件设计/架构/最佳实践问题,我知道在大多数情况下有更好的方法来访问这些数据成员。
答:
认为确实如此,但很好奇它是否受到 ISO C++ 标准的保证?
不是,在 or 成员之间可以有任何任意填充,这两个示例之间不必一致。这适用于 ISO 标准 C++ 和 ISO 标准 C。union
float
但是,如果没有充分的理由添加此类填充,则添加它没有任何意义。类布局是 ABI 的一部分,因此在编译所假定的 C++ ABI 或基础 C ABI 的规范中指定。您可以在相应的 ABI 规范中获得特定编译器/平台组合的明确答案。
问题编辑后:
offsetof(Vec0, x /*or r h*/) == offsetof(Vec1, x)
保证所有选项,因为 和 在您的示例中是标准布局。因此,所有这些偏移量都必须完全是 。Vec0
Vec1
0
另一方面
offsetof(Vec0, y /*or g s*/) == offsetof(Vec1, y)
offsetof(Vec0, z /*or b v*/) == offsetof(Vec1, z)
在任何情况下,C++ 标准都不能保证。第一个(和后续)成员之后的填充在两个类之间可能不同,尽管我看不出 ABI 在您的特定示例中做出该选择的任何充分理由。
这可能属于布局兼容的类别
Vec0
并且布局不兼容。它已经无法满足链接中列出的要求,因为单个非类成员(如)永远不能与(联合)类成员(如第一个匿名联合)在布局上兼容。Vec1
Vec1::x
Vec0
请注意,类型与布局不兼容并不意味着其成员不会具有相同的布局。它只是指定了一个他们实际上必须这样做的特定条件。布局兼容性条件仅与类的一个非常具体的用法相关,即当两者都显示为联合的成员时,在这种情况下,该联合的活动成员规则存在例外。这是布局兼容性与语言相关的唯一情况。
我还对天气的子情况感兴趣,或者不是 offsetof(但不一定是 offsetof,因为人们可能无法在 struct/class/etc 之外使用 offsetof,也许除了假设它能够访问 struct/class/etc 之外的私有/受保护数据成员)如果所有数据成员都设为私有/受保护,则两者之间的每个数据成员都是相同的。
如果不是所有成员都具有相同的可访问性 (//),则该类不再是标准布局类,甚至第一个成员位于偏移量零的保证也不再成立。private
protected
public
评论
float
union { float x, r, h; }
请注意,虽然另一个答案正确地指出您的尝试失败,但有一个替代表达式公式在内部和Vec1
union Vec2
{
struct { float x, y, z; } location;
struct { float r, g, b; } color;
struct { float h, s, v; } light;
};
许多编译器允许您省略名称 、 作为扩展名,但这不符合标准。location
color
light
评论
std::variant
static_assert
variant
x
x
r
h