想象一下:
int X;
X = X;
这将是未定义的行为
1在以下情况下,行为未定义:
[...]
使用具有自动存储持续时间的对象的值 不确定(6.2.4,6.7.8,6.8)。
但是这个怎么样?
int X;
X;
引用X;
引用引号是否允许编译器导致未定义的行为?或者这不算X被“使用”了吗?
答案 0 :(得分:5)
在C 1999中,使用未初始化的对象并不是直接错误。 (附件J中的引用不是标准的标准部分;它们只是提供信息。)具有自动存储持续时间的未初始化对象具有不确定的值。对于某些对象,该值可能是陷阱表示,因此使用它可能会导致未定义的行为。
但是,对于某些对象,可以确定未初始化的对象不能具有陷阱值。例如,unsigned char
不能有陷阱值,stdint.h
中定义的精确宽度有符号整数类型不能有陷阱值(因为它们是没有填充位的二进制补码)。对于其他类型,可能是由C实现定义的属性导致它们没有陷阱值。使用未初始化的int X
在所有C 1999实现中都没有定义的行为(但在某些实现中),但是使用未初始化的unsigned char X
会这样做。
在C 2011中,这个文本被添加到6.3.2 2中:“如果左值指定了一个自动存储持续时间的对象,该对象可以用寄存器存储类声明(从未有过它的地址)并且该对象未初始化(未使用初始化程序声明,并且在使用之前未对其进行任何分配),行为未定义。“因此,在C 2011中,X = X;
和{{1}有未定义的行为。
历史/背景:
C 2011更改支持Hewlett-Packard机器,该机器具有某些寄存器的特殊标志,用于指示寄存器内容是否有效。如果在内容无效的情况下使用寄存器,则机器可能会生成异常。因此,如果编译器将X;
X
分配给这样的寄存器,则当寄存器无效时使用该寄存器可能会导致机器中出现异常,即使没有unsigned char X
陷阱值。
答案 1 :(得分:0)
X = X;
以上是未定义的行为。因为X
未初始化。编译器至少应该生成一个警告。
标准规定6.3.2.1p2:
如果左值指定了一个可以使用寄存器存储类声明的自动存储持续时间的对象(从未使用过其地址),并且该对象未初始化(未使用初始化程序声明,并且未对其进行任何赋值)在使用之前),行为未定义。
然而:
X;
以上类似于:
1212342413;
由于X
会评估某种表达方式。