【发布时间】:2023-03-29 05:35:01
【问题描述】:
我正在尝试解释 C11 standard 在未显式初始化时关于联合的静态(和线程本地)初始化。
第 6.7.9 节 10(第 139 页)规定如下:
如果具有自动存储持续时间的对象未显式初始化,则其值是不确定的。如果具有静态或线程存储持续时间的对象未显式初始化,则:
——如果是指针类型,则初始化为空指针;
——如果是算术类型,则初始化为(正或无符号)零;
——如果是聚合,每个成员都根据这些规则进行初始化(递归),任何填充都初始化为零位;
——如果是联合,则根据这些规则(递归地)初始化第一个命名的成员,并将任何填充初始化为零位;
假设我们在 amd64 架构上,给定以下语句:
static union { uint32_t x; uint16_t y[3]; } u;
u.y[2] 可以包含非零值,还是因为被视为填充而将其初始化为零?
我已经浏览了 C11 标准,但几乎没有解释什么是联合中的填充。在C99 standard (pg 126) 中没有提到填充,所以在这种情况下u.y[2] 可以是非零的。
【问题讨论】:
-
你的意思是
u.y[3]? 我的理解是如果联合需要一些填充,它将被初始化为0。假设你需要在你的架构上进行4字节对齐并且 y[3] 是 6 个字节并且需要 2 个字节对齐,那么最终对齐需要是 8 的倍数,因此您将有 2 个字节填充(基本上在 uy[3])。这将是 0。 -
@PSkocik:我错了,联合可以在任何成员之外的末尾有填充,当一个成员是一个对齐不太严格的数组时,它不会填充更多所需的空间- 另一个成员的严格对齐(并且数组也比另一个成员大,因此其他成员本身不会填充所需的空间)。
-
在联合本身(而不是其成员)中的填充标准中唯一明确提及的是可能位于末尾的填充,如示例中的
u.y[3]这个问题。作为 C 实现的消费者,我必须将这个问题询问的段落解释为告诉我尾随填充已初始化为零,而不是告诉我y中的字节而不是x中的字节(因此@ 987654330@) 被初始化为零。作为实现开发人员,我可能会采取预防措施,将所有字节初始化为零。
标签: c language-lawyer c11