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

时间:2019-10-15 15:37:39

标签: c language-lawyer addressof lvalue-to-rvalue register-keyword

来自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有什么期望?

2 个答案:

答案 0 :(得分:2)

在这种情况下,由于x已获取地址,因此行为并非严格未定义。此时x的值为不确定的。这意味着该值为陷阱表示未指定

如果x恰好包含陷阱表示,则该行为未定义,否则该值未指定,这意味着可以打印任何有效值。

此外,您可能会遇到的大多数系统都没有整数类型的填充位,这意味着该实现上没有陷阱表示,并且值始终为未指定。< / p>

C standard的相关段落:

第3.19节:

  

3.19.2

     

1 不确定值是未指定的值还是陷阱的表示形式

     

3.19.3

     

1 未指定值本国际标准未规定任何要求的相关类型的有效值   在任何情况下选择哪个值

     

2 注意未指定的值不能是陷阱表示。

     

3.19.4

     

1 陷阱表示不需要表示对象类型值的对象表示

第6.7.9p10节:

  

如果具有自动存储持续时间的对象不是   显式初始化,其值不确定。

答案 1 :(得分:0)

除其他事项外,该标准使用术语“未定义的行为”来描述一般情况,在这些情况下,绝大多数实现将以相同的可预测的一般方式运行,但是某些特定的实现可能通过行为不同而更好地为客户提供服务。

考虑以下功能:

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],而这些结构的其他元素则保留它们以前保存的内容。他们并没有试图确切地描述应该允许哪种类型的优化,而是仅仅假设实现将寻求最佳地满足其客户的需求。