Dav*_*nan 74 c undefined-behavior
考虑这个程序:
#include <stdio.h>
int main(void)
{
unsigned int a;
printf("%u %u\n", a^a, a-a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
是不确定的行为?
从表面上看,它a
是一个未初始化的变量.所以这指向未定义的行为.但是a^a
并且a-a
等于0
所有的价值a
,至少我认为是这样的.有可能有某种方式来证明行为是明确定义的吗?
M.M*_*M.M 72
在C11中:
a
从未使用过地址,则根据6.3.2.1/2显式未定义(引用如下)某些对象表示不需要表示对象类型的值.
无符号整数可以具有陷阱表示(例如,如果它具有15个精度位和1个奇偶校验位,则访问a
可能导致奇偶校验错误).
6.2.4/6表示初始值是不确定的,3.19.2中的定义是未指定的值或陷阱表示.
此外:正如Pascal Cuoq所指出的那样,在C11 6.3.2.1/2中:
如果左值指定了一个自动存储持续时间的对象,该对象可以使用寄存器存储类声明(从未使用其地址),并且该对象未初始化(未使用初始化程序声明,并且在使用之前未对其进行任何赋值) ),行为未定义.
这对于字符类型没有例外,因此该条款似乎取代了前面的讨论; x
即使没有陷阱表示,访问也会立即未定义.此子句已添加到C11以支持实际上具有寄存器陷阱状态的Itanium CPU.
没有陷阱表示的系统:但是如果我们投入&x;
使6.3.2.1/2的异议不再适用,并且我们在一个已知没有陷阱表示的系统上呢?然后该值是未指定的值.3.19.3 中未指定值的定义有点模糊,但DR 451澄清了这一点,其结论如下:
根据该决议,int a; &a; int b = a - a;
结果b
仍然具有不确定的价值.
请注意,如果不确定的值未传递给库函数,我们仍然处于未指定行为的范围(不是未定义的行为).结果可能很奇怪,例如if ( j != j ) foo();
可以称之为foo,但是恶魔必须保持在鼻腔中.
AnT*_*AnT 32
是的,这是未定义的行为.
首先,任何未初始化的变量都可以具有"破碎"(又称"陷阱")表示.即使单次尝试访问该表示也会触发未定义的行为.此外,即使是非陷阱类型(如unsigned char
)的对象仍然可以获得特殊的平台相关状态(如NaT - Not-A-Thing - on Itanium),这些状态可能表现为其"不确定值".
其次,未初始化的变量不能保证具有稳定的值.对同一个未初始化变量的两次顺序访问可以读取完全不同的值,这就是为什么即使两个访问a - a
都是"成功"(不是陷阱),仍然不能保证a - a
将评估为零.