从6.3.2.1 (强调地雷)
如果lvalue指定可以用寄存器存储类(从未获取其地址)声明的自动存储持续时间对象,且该对象未初始化(未使用初始化器声明,且未在使用前对其执行赋值),则行为未定义。
这意味着,如果无法用寄存器存储类声明自动对象(获取其地址):
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
中期望什么?
发布于 2019-10-15 07:47:50
在这种情况下,因为x
已经将它的地址取下来了,所以行为并不是严格不定义的。此时indeterminate.是x
的值。这意味着该值要么是陷阱表示,要么是未指定的。
如果x
碰巧包含一个陷阱表示,则该行为未定义,否则该值未指定,这意味着可以打印任何有效值。
而且,您可能遇到的大多数系统在整数类型中没有任何填充位,这意味着在该实现上没有陷阱表示,并且值始终是未指定的。
C标准的相关文章
第3.19款:
3.19.2 1不确定值或未指定值或陷阱表示 3.19.3 1国际标准不要求在任何实例中选择值的相关类型的未指定值有效值 2注意,未指定的值不能是陷阱表示。 3.19.4 1陷阱表示不需要表示对象类型的值的对象表示
第6.7.9p10节:
如果没有显式初始化具有自动存储持续时间的对象,则其值是不确定的。
发布于 2019-10-15 07:51:09
标准使用“未定义的行为”这一术语来描述大多数实现都会以相同的可预测的一般方式进行操作的一般情况,但是某些特定的实现可以通过不同的行为更好地服务于客户。
考虑以下职能:
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]
,同时让这些结构的其他元素保存他们以前持有的东西。他们没有试图准确地描述应该允许哪种类型的优化,而是简单地假设实现将寻求最好地满足客户的需求。
https://stackoverflow.com/questions/58398279
复制