C 是否使用未指定所有成员的结构?
在块范围内考虑此代码:C 是否使用未指定所有成员的结构?,c,struct,language-lawyer,undefined-behavior,C,Struct,Language Lawyer,Undefined Behavior,在块范围内考虑此代码: struct foo { unsigned char a; unsigned char b; } x, y; x.a = 0; y = x; C[N1570]6.3.2.1 2表示“如果左值指定了一个自动存储持续时间的对象,该对象本可以用寄存器存储类声明(从未获取其地址),并且该对象未初始化(未用初始值设定项声明,并且在使用前未对其进行赋值),该行为未定义。“ 虽然已为x的成员分配了一个值,但未执行对x的分配,也未获取其地址。因此,似乎6.3.2.12告诉我们y=x中x
struct foo { unsigned char a; unsigned char b; } x, y;
x.a = 0;
y = x;
C[N1570]6.3.2.1 2表示“如果左值指定了一个自动存储持续时间的对象,该对象本可以用寄存器存储类声明(从未获取其地址),并且该对象未初始化(未用初始值设定项声明,并且在使用前未对其进行赋值),该行为未定义。“
虽然已为x
的成员分配了一个值,但未执行对x
的分配,也未获取其地址。因此,似乎6.3.2.12告诉我们y=x
中x
的行为未定义
但是,如果我们给<代码> x < />代码中的每一个成员赋值,考虑到<代码> x <代码>,对于63.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,即使结构已初始化,未命名的成员也具有不确定的值。)我的观点是,这是未定义的行为,因为标准未明确定义。从4合规性§2(强调我的): …未定义的行为是另一种行为 在本国际标准中用“未定义行为”或 省略任何明确的行为定义 在多次阅读N1570草稿之后,我找不到任何关于使用部分初始化结构的行为的明确定义。一方面,第6.3.2.1条第2款规定: …如果 左值指定了一个自动存储持续时间的对象,该对象可以 使用寄存器存储类声明(从未获取其地址),以及该对象 未初始化(未使用初始值设定项声明,且未对其进行赋值) 在使用前执行),行为未定义 所以这里的
x
是自动的,从来没有被初始化过(只有一个成员),令人钦佩的是,它的地址从来没有被取过,所以我们可以认为它是明确的UB
另一方面,6.2.6.1§6规定:
。。。结构或联合对象的值永远不是陷阱表示,即使结构或联合对象的成员的值可能是陷阱表示
正如6.2.6.1§5刚刚定义的陷阱表示:
某些对象表示不需要表示对象类型的值。如果存储
对象的值具有这样的表示形式,并由一个左值表达式读取,该表达式
没有字符类型,行为未定义。如果提出了这样的陈述
通过一个左值表达式修改对象的全部或任何部分的副作用,左值表达式表示a
成员的0值和b
成员的未定义值。
没有字符类型,行为未定义。50)调用这样的表示
陷阱表示法
我们可以认为,获取结构的值始终是合法的,因为它不能是陷阱表示
此外,我还不清楚设置结构成员的值是否会使结构处于单位化状态
基于所有这些原因,我认为该标准没有明确界定行为应该是什么,只是出于这个原因,它是未定义的行为
也就是说,我非常确定任何通用编译器都会接受它,并将
y
给出x
的当前表示形式,这意味着a
成员的值为0,而b
成员的值与x.b
当前表示形式相同 C标准规定结构类型不能有陷阱表示,尽管结构的成员可能有陷阱表示。在涉及部分书面结构的情况下,该担保将是有用的。此外,在编写所有成员之前禁止复制结构,即使是副本接收者永远不会使用的结构,这将要求程序员编写不必要的低效代码,并且没有任何有用的用途。以“优化”的名义强加这样的要求将是彻头彻尾的愚蠢,而且我不知道有任何证据表明该标准的作者有意这么做
不幸的是,标准的作者使用相同的术语来描述两种情况: