仅供参考,尝试理解本文
中的示例总结如下:
int foo(int *a, long *b)
{
int t = *a;
*b = 0; // cannot change *a
return *a - t; // can be folded to zero
}
int bar(int *a, long *b)
{
int t = *a;
for (int i = 0; i != sizeof *b; ++i)
((unsigned char*)b)[i] = 0;
return *a - t; // must not be folded
}
文章声称 foo 的返回可以被折叠,因为
因为 a 和 b 被声明为指向不兼容类型的指针,并且因为 C 和 C++ 要求对象的存储值只能由兼容类型的左值访问,所以对 *b 的存储不能影响缓存在 *a 中的值变量 t
...但我不明白为什么酒吧里有什么不同。什么代码/事件序列会使折叠无效?
foo
中,赋值 *b = 0
不会影响 *a
,因为在严格的别名规则下,类型是不兼容的。这使得编译器可以安全地将 *a - t
折叠为零。unsigned char*
并逐字节写入意味着编译器必须考虑到 *a
在循环中被修改的可能性。因此,不能假设 *a - t
的值为零,编译器必须避免折叠该表达式。关键区别在于
unsigned char*
是一种绕过严格别名规则的特殊类型,允许通过 int
间接修改 a
指向的 b
对象。