来自 6.3.2.1(强调我的(
如果左值指定自动存储持续时间的对象可以使用寄存器存储类声明(从来没有 其地址(和该对象未初始化(未声明( 使用初始值设定项,并且之前未对其执行任何赋值 使用(,行为未定义。
这意味着,如果自动对象无法使用寄存器存储类声明(获取其地址(:
int x;
printf("just a dummy pointer print %p", &x); //taking the address to break 6.3.2.1 UB condition
if (x == 2)
{
print("x uninitialized value: %d", x);
}
根据 6.3.2.1,在我使用未初始化对象的值的if (x == 2)
中没有未定义的行为。 如果这是真的,并且这里没有UB,那么定义的行为是什么?根据标准,我应该在x
中期待什么?
在这种情况下,由于x
的地址已被获取,因此行为并非严格未定义。 此时x
的值是不确定的。 这意味着该值要么是陷阱表示形式,要么是未指定的。
如果x
恰好包含陷阱表示形式,则行为未定义,否则未指定值,这意味着可以打印任何有效值。
此外,您可能会遇到的大多数系统在整数类型中没有任何填充位,这意味着该实现上没有陷阱表示形式,并且值将始终未指定。
C标准的相关段落:
第3.19节:
3.19.2
1 个不确定值,未指定的值或陷阱表示形式
3.19.3
1个未指定的相关类型的有效值,本标准对 在任何实例中选择哪个值
2注意 未指定的值不能是陷印表示。
3.19.4
1 陷阱表示 不需要表示对象类型值的对象表示
第 6.7.9p10 节:
如果具有自动存储持续时间的对象不是 显式初始化,其值不确定。
该标准使用术语"未定义的行为"来描述一般情况,其中绝大多数实现将以相同的可预测的一般方式运行,但某些特定实现可能通过不同的行为更好地为其客户服务。
请考虑以下函数:
struct foo { unsigned char dat[256]; };
struct foo x,y;
void test(int a, int b)
{
struct foo temp;
temp.dat[a] = 1;
temp.dat[b] = 2;
x=temp;
y=temp;
}
我不认为该标准的作者想要求程序员在存储之前完全初始化temp
,但我也不认为他们想禁止实现简单地写入x.dat[a]
、y.dat[a]
、x.dat[b]
和y.dat[b]
,同时让这些结构的其他元素保留他们以前持有的任何内容。 他们没有试图准确描述应该允许什么样的优化,而只是假设实现将寻求最好地满足客户的需求。