use*_*248 0 c struct initialization undefined-behavior language-lawyer
在 C 中,使用未初始化的变量是未定义的行为。包括:
int x;
int y = x;
Run Code Online (Sandbox Code Playgroud)
但是,假设我有以下内容:
struct Struct {
int a;
int b;
};
struct Struct s;
s.a = 1;
struct Struct s0 = s;
return s; // Assuming an enclosing function with the correct return type
Run Code Online (Sandbox Code Playgroud)
如果某些元素(但不是全部)已被分配,上述代码是否会调用未定义的行为?
C 标准没有充分解决这个问题,但合理的 C 实现支持在某些成员未初始化时使用整个结构。对于任何 C 实现都有一个简单的解决方法。
\n请注意,\xe2\x80\x9c在 C 中,使用未初始化的变量是未定义的行为\xe2\x80\x9d 并不完全正确。根据 C 2018 6.7.9 10 ,具有自动存储持续时间的未初始化对象的值是不确定的。如果满足以下条件,则使用此类对象的值具有未定义的行为:未获取其地址,则
\n\n\n\xe2\x80\xa6 如果左值指定一个可以使用存储类声明的自动存储持续时间的对象
\nregister(从未获取其地址),并且该对象未初始化(未使用初始值设定项声明且没有对其进行赋值)在使用之前执行),该行为是未定义的。
因此,为了确保使用结构不会有未定义的行为,只需获取其地址即可。假设你有一些结构对象s。然后我们只需输入(void) &s;代码即可获取它的地址(并丢弃它)。通过获取其地址,我们可以防止该对象被声明register,因此 6.3.2.1 2 将不适用。
仍然可能有人担心使用具有不确定值的对象可能会遇到陷阱表示。然而,根据 6.2.6.1 2,这种情况不会发生在结构上:
\n\n\n\xe2\x80\xa6 结构或联合对象的值永远不是陷阱表示,即使结构或联合对象的成员值可能是陷阱表示。
\n
该段落告诉我们,C 委员会希望 C 程序能够使用整个结构,即使其成员并未全部初始化。6.3.2.1 2、关于某些未初始化对象的未定义行为是后来添加的,以提供允许处理器跟踪未初始化寄存器的惠普功能。当添加该内容时,委员会没有添加类似于 6.2.6.1 2 的声明,告诉我们它不适用于结构。
\n我的观点是,6.2.6.1 2 表明其目的是为了安全地复制整个结构,而 6.3.2.1 2 无意改变这一点。然而,为了完全安全,按照上面的解释获取结构的地址可以确保访问该结构不会出现未定义的行为,无论在这方面标准的 one\xe2\x80\x99s 解释如何。
\n