【发布时间】:2018-05-06 02:15:17
【问题描述】:
在块范围内考虑这段代码:
struct foo { unsigned char a; unsigned char b; } x, y;
x.a = 0;
y = x;
C [N1570] 6.3.2.1 2 说“如果左值指定了一个可以使用 register 存储类声明的具有自动存储持续时间的对象(从未占用其地址),并且对象未初始化(未使用初始化程序声明,并且在使用之前未对其执行任何赋值),行为未定义。”
虽然x 的成员已被赋值,但尚未执行对x 的赋值,其地址也未被占用。因此,看来 6.3.2.1 2 告诉我们x 在y = x 中的行为是未定义的。
但是,如果我们为x 的每个成员都分配了一个值,那么将x 视为出于6.3.2.1 2 的目的未初始化似乎是不合理的。
(1) 严格来说,标准中是否有任何内容导致 6.3.2.1 2 不适用于(使未定义)上述代码?
(2) 假设我们正在修改标准或确定对 6.3.2.1 2 的合理修改,是否有理由更喜欢以下其中之一? (a) 6.3.2.1 2 不适用于结构。 (b) 如果结构的至少一个成员已被赋值,则该结构不会为 6.3.2.1 2 的目的而未初始化。 (c) 如果结构的所有命名1 成员已为 6.3.2.1 2 分配了一个值,该结构不会未初始化。
脚注
1 结构可能有未命名的成员,因此并不总是可以为结构的每个成员赋值。 (根据 6.7.9 9,即使结构已初始化,未命名的成员也具有不确定的值。)
【问题讨论】:
-
在 C++ 中,它是 UB,因为可能会捕获
int,并且默认的复制构造函数执行成员复制。见stackoverflow.com/questions/9163555/…。但是 C 和 C++ 在这类事情上的分歧相当大。我不认为 C 副本以相同的方式工作。不幸的是,高于我的工资等级,但 FWIW 我倾向于“是的,这是 UB 方面”。 -
@Bathsheba 我倾向于另一边,因为如果不确定值是陷阱表示,则读取未初始化的值只是 UB,而
int值很少(如果有的话?)有这些。另一方面,there's this 所以我不再那么确定了。真的高于我的工资等级...... :) -
@EricPostpischil:因此,为了避免学究,修改问题以使用
unsigned char类型是否明智? -
我刚刚编辑使用
unsigned char明确表示我们对陷阱表示不感兴趣,只是对 6.3.2.1 2 的含义。 -
@Bathsheba:是的。起初我不愿意编辑这个问题,以防对起草答案的人有点不公平。但显然我需要采取先发制人的措施。
标签: c struct language-lawyer undefined-behavior