4

我有以下类型:

union {
  struct {
    uint32_t c0;
    uint32_t k0[4];
    uint32_t c1;
    uint32_t v[2];
    uint32_t i[2];
    uint32_t c2;
    uint32_t k1[4];
    uint32_t c3;
  } named;
  uint32_t array[16];
} state;

因为“named”中的每个字段在初始化时都有含义,但之后我将主要将其用作单词数组。C 是否保证 that与, is等state.array[0]相同?state.named.c0state.array[1]state.named.k0[0]

如果没有,它有多大可能起作用?如果我依赖它,是否有任何编译器/平台会破坏我的代码?

4

3 回答 3

3

要回答您最令人担忧的问题,“..它有多大可能起作用”,除非它是确定的事情,否则不要赌可能性。在这种情况下不是。

标准(§6.7.2.1,p15)规定结构的第一个成员或联合的所有成员的地址与结构或联合本身的地址相同。对您来说,这仅意味着 和 的地址相同,array[16]并且named两者都等同于 的地址state。但是,如果没有实现相关的打包,则无法保证结构将精确覆盖,因为标准的同一部分指出结构间打包是可能的。

例如,无论出于何种原因,使用打包方案以始终在 64 位边界上启动成员的编译器可能会将您的布局name如下:

struct {
    uint32_t c0;
    **padding 4 bytes**
    uint32_t k0[4];
    uint32_t c1;
    **padding 4 bytes**
    uint32_t v[2];
    uint32_t i[2];
    uint32_t c2;
    **padding 4 bytes**
    uint32_t k1[4];
    uint32_t c3;
    **padding 4 bytes**
} name;

简而言之,您可以保证的是,name 整体占用的内存和工会中其他成员array[16]占用的内存应该占用相同的内存,从每个内存的开头可寻址位置开始。name该内存在's 打包下的外观取决于实现以及您希望提供的任何打包提示。

标准的一些相关部分:

C99-§6.7.2.1,p6 如 6.2.5 所述,结构是由成员序列组成的类型,其存储按有序序列分配,联合是由成员序列组成的类型,其存储重叠。

C99-§6.7.2.1,p15 在结构对象中,非位域成员和位域所在的单元的地址按声明顺序递增。一个指向结构对象的指针,经过适当的转换,指向它的初始成员(或者如果该成员是位域,则指向它所在的单元),反之亦然。结构对象中可能有未命名的填充,但不是在其开头。

C99-§6.7.2.1,p16 联合体的大小足以容纳其最大的成员。任何时候最多可以将其中一个成员的值存储在联合对象中。一个指向联合对象的指针,经过适当的转换,指向它的每个成员(或者如果一个成员是位域,则指向它所在的单元),反之亦然。

C99-§6.7.2.1,p17 在结构或联合的末尾可能有未命名的填充。

于 2013-01-22T03:56:43.940 回答
2

来自 C 标准:

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

6.7.2.1/16 联合体
的规模足以容纳其最大的成员。任何时候最多可以将其中一个成员的值存储在联合对象中。一个指向联合对象的指针,经过适当的转换,指向它的每个成员(或者如果一个成员是一个位域,则指向它所在的单元),反之亦然。

强调我的。这基本上转化为state.named,state.named.c0state.array具有相同的地址。但是,这里有个问题,不能保证named's 的其余成员所在的位置(指定了内存中的顺序,但没有指定位置)。从技术上讲,可以在每个named's 成员之间进行填充(甚至在结尾处named)。所以答案是否定的,这不能保证。可以在成员之间添加填充。

关键是第一句的最后一句话:

结构对象中可能存在未命名的填充

于 2013-01-22T03:57:10.410 回答
-3

state.array[0]的 与 相同state.named.c0。C 保证 'array[16]' 和命名的结构将占用相同的内存区域。

只要数据类型匹配,这是真的。例如,如果您存储 2 个排序然后读取一个整数,则结果取决于机器。

于 2013-01-22T03:57:08.237 回答