struct members内存布局

时间:2011-10-17 12:35:54

标签: c++ c

如果我有这样的结构:

struct S {
    ANY_TYPE a;
    ANY_TYPE b;
    ANY_TYPE c;
} s;

我可以安全地假设以下假设在所有平台上始终都是正确的吗?

((char *)&s.a) < ((char *)&s.c)
((char *)&s.a + sizeof(s.a) + sizeof(s.b)) <= ((char *)&s.c)

在C ++中呢?

6 个答案:

答案 0 :(得分:5)

对于结构体来说,这是正确的,但只要引入访问说明符,就会对C ++进行更改。允许编译器重新排序由访问说明符分隔的整个块。

答案 1 :(得分:4)

是的,至少在C中。编译器可以在任何结构成员之后自由插入填充,但不能对成员重新排序。

它也必须在第一个成员之前插入填充。

来自C99,6.7.2.1

  

13 / 在结构对象中,非位字段成员和位字所在的单位具有按声明顺序增加的地址。指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。在结构对象中可能有未命名的填充,但不是在它的开头。

     

15 / 结构或联合的末尾可能有未命名的填充。

答案 2 :(得分:2)

这在C ++ 20中有所变化(至少是当前草案):如果用a注释bc[[no_unique_address]],而它们恰好是空结构,它们都可能具有相同的地址。

实际上,它更复杂-如果任何两个为空并带有注释,则所有3个都可以共享一个地址。

答案 3 :(得分:1)

在C ++中,您可以确定这些假设将成立。在像这样的结构中,不允许编译器改变成员的顺序。

答案 4 :(得分:0)

是的,默认情况下,C ++编译器不允许在结构中移动元素,这使得两个语句都很简单。

答案 5 :(得分:0)

  1. 是(只要sizeof(ANY_TYPE)不为0.有些编译器允许它,这是非标准的 - 请参阅Can sizeof return 0 (zero))。使用&lt; =或者假设标准编译器是安全的。

  2. 在C ++中也是如此。

    指针比较仅在数组和结构/类中有意义,而不是一般。