C语言 使用未初始化的变量而不调用未定义的行为



来自 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],同时让这些结构的其他元素保留他们以前持有的任何内容。 他们没有试图准确描述应该允许什么样的优化,而只是假设实现将寻求最好地满足客户的需求。

最新更新