如果我有:
unsigned int x;
x -= x;
很明显x
should在这个表达式之后为零,但是我到处都看到,他们说behavior这段代码的值是未定义的,而不仅仅是x
(直到减法之前)。
两个问题:
显然,编译器可以简单地使用whatever它认为变量内“方便”的垃圾值,并且它将按预期工作......这种方法有什么问题?
是的,这种行为是未定义的,但其原因与大多数人意识到的不同。
首先,使用统一值本身并不是未定义的行为,但该值只是不确定的。如果该值恰好是该类型的陷阱表示,那么访问它就是 UB。无符号类型很少有陷阱表示,因此在这方面你会相对安全。
使行为未定义的原因是变量的附加属性,即它“可以用以下方式声明”register
“也就是说,它的地址永远不会被获取。此类变量会被特殊处理,因为有些架构具有真正的 CPU 寄存器,这些寄存器具有某种“未初始化”的额外状态,并且与类型域中的值不对应。
Edit:标准的相关短语是6.3.2.1p2:
如果左值指定自动存储持续时间的对象
可以用寄存器存储类来声明(从来没有
它的地址已被占用),并且该对象未初始化(未声明
带有初始化器并且之前没有对其进行赋值
使用),行为未定义。
为了更清楚地说明,以下代码is在所有情况下均合法:
unsigned char a, b;
memcpy(&a, &b, 1);
a -= a;
- 这里的地址
a
and b
被采取,所以他们的价值只是
不定。
- Since
unsigned char
从来没有陷阱表示
该不确定值只是未指定,任何值unsigned char
可以
发生。
- 在最后
a
must保持价值0
.
Edit2: a
and b
有未指定的值:
3.19.3 未指定值
相关类型的有效值,本国际标准对哪个值没有要求
在任何情况下都被选择
Edit3:其中一些将在 C23 中得到澄清,其中术语“不确定值”被术语“不确定表示”替换,术语“陷阱表示”被“非值表示”替换。另请注意,所有这些在 C 和 C++ 之间都是不同的,它们具有不同的对象模型。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)