C / C ++联合中元素的内存位置

时间:2016-04-24 14:48:17

标签: c++ c c++11 unions c11

我在C中有一个像这样的联盟:

union AUnion {
  struct CharBuf {
    char *buf;
    size_t len;
  } charbuf;
  uint8_t num;
  double fp_num;
};

我的问题是,如果给出以下内容,我可以保证:

union AUnion u;

以下是真的:

&u == &u.num
&u == &u.fp_num
&u == &u.charbuf

即,它们都始于存储u的内存段的开头。

对于使用gcc version 5.3.0-std=c11编译的此C程序,上述情况属实:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

union AUnion {
    struct CharBuf {
        char *buf;
        size_t len;
    } charbuf;
    uint8_t num;
    double fp_num;
};

int main(void)
{
    union AUnion u;
    printf("%d\n", ((void*)&u) == ((void*)&u.charbuf));
    printf("%d\n", ((void*)&u.charbuf) == ((void*)&u.num));
    printf("%d\n", ((void*)&u.num) == ((void*)&u.fp_num));
}

打印时:

1
1
1

使用相同的编译器将上面的代码编译为C ++ 11会产生与将其编译为C11相同的输出。

但这是标准化行为吗?这是不确定的?我可以依赖大多数C编译器的这种行为吗?我也可以期待C ++编译器的这种行为吗?

2 个答案:

答案 0 :(得分:13)

6.7.2.1p16中,C标准保证:

  

联合的大小足以包含其最大的成员。最多一个成员的值可以随时存储在union对象中。 指向联合对象的指针(适当转换)指向其每个成员(或者如果成员是位字段,则指向它所在的单位),反之亦然。

所以,是的,你可以依赖从union地址开始的所有成员(注意struct的第一个成员也是如此)。

C ++标准包含一个与C风格相似的句子(即只有C风格的成员)union s / struct,因为C ++允许将union传递给C函数确实需要这种布局.C ++标准中的相关部分是9.5。

但是,请注意标准简单类型(整数,浮点数)中可能存在填充。他们的内部可能会有所不同(结束)。您还可能违反严格别名规则(C:有效类型)。

答案 1 :(得分:10)

根据我的经验,我会说“是的”,虽然我已经检查了C++14 standard,但它甚至保证了这一点。 (c ++ 11很可能会产生相同的效果)第9.5章规定:All non-static data members of a union object have the same address

所以,你可以依赖这种行为。