如果我有:
unsigned int x;
x -= x;
Run Code Online (Sandbox Code Playgroud)
很明显,x 应该这样表达后是零,但到处看,他们说的行为,这种代码是不确定的,而不是仅仅值x(直到减法之前).
两个问题:
这段代码的行为确实未定义吗?
(例如,代码在兼容系统上崩溃[或更糟]?)
如果是这样,为什么 C表示行为是未定义的,当非常清楚x这里应该为零时?
即不在此定义行为给出的优势是什么?
很明显,编译器可以简单地使用它在变量中认为"方便"的任何垃圾值,并且它可以按预期工作......这种方法有什么问题?
是使用未初始化的变量作为src对memcpy用C未定义行为?
void foo(int *to)
{
int from;
memcpy(to, &from, sizeof(from));
}
Run Code Online (Sandbox Code Playgroud) 我清楚了解了我对价值初始化与默认初始化的理解,并且发现了这个:
struct C {
int x;
int y;
C () { }
};
int main () {
C c = C ();
}
Run Code Online (Sandbox Code Playgroud)
显然这是UB,因为
在C()的情况下,有一个能够初始化x和y成员的构造函数,因此不会进行初始化.因此,尝试将C()复制到c会导致未定义的行为.
我想我理解为什么,但我不确定.有人可以详细说明吗?
这是否意味着这也是UB?
int x; x = x;
Run Code Online (Sandbox Code Playgroud)
顺便提一下,关于值初始化,以下是否保证为零?
int x = int ();
Run Code Online (Sandbox Code Playgroud) 在ia64上,每个64位寄存器实际上是65位.额外的位被称为"NaT",代表"不是一件事".当寄存器不包含有效值时,该位置1.可以将其视为浮点NaN的整数版本.
NaT位最常见于推测执行.在ia64上有一种特殊形式的加载指令,它试图从内存中加载值,但是如果加载失败(因为内存被分页或地址无效),那么所有发生的事情都会发生,而不是引发页面错误是NaT位被设置,并继续执行.
NaT的所有数学运算都会再次产生NaT.
源文章接着解释了在推测加载期间寄存器如何最终具有NaT表示并发出以下注释:
对于你看,如果你有一个值为NaT的寄存器,并且你以错误的方式呼吸(例如,尝试将其值保存到内存中),处理器将引发STATUS_REG_NAT_CONSUMPTION异常.
似乎从陷阱表示的其他堆栈溢出答案,
"任何类型(unsigned char除外)可能有陷阱表示".
这个链接说明了
标准给出的关于访问未初始化数据的唯一保证是unsigned char类型没有陷阱表示,并且该padding没有陷阱表示.
如果这样的寄存器(具有NaT位设置的寄存器)被分配用于存储未初始化的无符号字符(类似于下面的缺陷报告中的代码片段),那么如何根据ISO C11处理?
以下缺陷报告是否指向同一问题,是否在ISO C11中得到纠正?
如果不是如何处理这种特殊情况?
如果左值指定了一个自动存储持续时间的对象,该对象可能已经使用寄存器存储类声明(从未使用过其地址),并且该对象未初始化(未使用初始化程序声明,并且未对其进行任何赋值)使用),行为未定义
在"更改为C1X"部分的缺陷报告末尾添加上述内容是否处理此案例?
以下函数在C90下具有未定义的行为,但在C99下似乎严格符合
int foo(void) {
unsigned char uc;
return uc + 1 >= 0;
}
Run Code Online (Sandbox Code Playgroud) 我有以下一段代码:
typedef struct {
int x;
int y;
int z;
int w;
} s32x4;
s32x4
f() {
s32x4 v;
v.x = 0
return v;
}
Run Code Online (Sandbox Code Playgroud)
生成(gcc -O2):
f:
xor eax, eax
xor edx, edx ; this line is questionable
ret
Run Code Online (Sandbox Code Playgroud)
其中 clang 输出(clang -O2):
f: # @f
xor eax, eax
ret
Run Code Online (Sandbox Code Playgroud)
GCC插入XOR那里?