违反严格的别名规则
在下面的代码中,让我们假设 float
和 uint32_t
具有相同的大小。
void fun(uint32_t* u, float* f) {
float a = *f
*u = 22;
float b = *f;
print("%g should equal %g\n", a, b);
}
u
和 f
具有不同的基类型,因此编译器可以假设它们指向不同的对象。在 a
和 b
的两次初始化之间*f
不可能发生变化,因此编译器可能会将代码优化为相当于
void fun(uint32_t* u, float* f) {
float a = *f
*u = 22;
print("%g should equal %g\n", a, a);
}
也就是说,*f
的第二次加载操作可以完全优化。
如果我们正常调用此函数
float fval = 4;
uint32_t uval = 77;
fun(&uval, &fval);
一切顺利,等等
4 应该等于 4
打印出来。但如果我们作弊并传递相同的指针,转换后,
float fval = 4;
uint32_t* up = (uint32_t*)&fval;
fun(up, &fval);
我们违反了严格的别名规则。然后行为变得不确定。输出可以如上所述,如果编译器优化了第二次访问,或者完全不同的东西,那么你的程序最终会处于完全不可靠的状态。