gpt4 book ai didi

c - 为什么转换不同的指针类型会导致 TBAA(基于类型的别名分析)违规?

转载 作者:太空狗 更新时间:2023-10-29 15:32:08 28 4
gpt4 key购买 nike

我正在读这个blog ,然后我发现了一些代码我真的不明白。为什么这是错误的代码?

float *P;

void zero_array() {
int i;
for (i = 0; i < 10000; ++i)
P[i] = 0.0f;
}

int main() {
P = (float*)&P; // cast causes TBAA violation in zero_array.
zero_array();
}

希望有人能解释一下。

最佳答案

以下代码:

float *P;
P = (float*)&P;
P[0] = 0.0f;

违反了严格的别名规则。

对象 P 具有有效类型 float *,因为那是它声明的类型。 C11 6.5/6:

The effective type of an object for an access to its stored value is the declared type of the object, if any.

第二行执行后,表达式P[0] 表示与P 相同的内存位置。 (注意:为了解释的目的,想象 sizeof(float) == sizeof(float *)。显然,如果这些大小不同,那么情况会更糟!)

执行 P[0] = 0.0f 使用 float 类型的左值来访问 float * 类型的对象。这违反了 6.5/7:

An object shall have its stored value accessed only by an lvalue expression that has one of the following types

在这些引用中,“访问”是指读或写。 “以下类型”列表不包括任何涵盖使用 float 表达式读取 float *

的异常

这个例子有点难以理解,因为它是 self 参照的。然而,它与这个更简单的示例的原理完全相同:

float *Q;
float *P = &Q;
*P = 0.0f;

在这种情况下,Q 的类型为 float *,但它是通过 float 类型的左值编写的。


此示例演示了该规则的基本原理。假设不存在严格的别名规则,并且允许所有别名。然后评估 P[0] = 0.0f 更改 P。在一个常见的实现中,这会导致 P 现在是一个空指针,但我们可以很容易地想象一些其他的值被赋值,这使得 P 成为指向其他变量的有效指针.

在这种情况下,行P[1] = 0.0f 必须成功写入另一个变量。因此,编译器将无法用 memset 替换循环;这样的 memset 会更新 P[1] 的原始位置,但不会更新 P[0] = ... 之后 P[1] 的新位置.; 已被执行。不允许优化改变程序的可观察行为。

严格别名规则的存在意味着编译器可以执行优化,例如将此循环更改为 memset,而不必担心循环的内容可能会动态更改指针。


注意。 P = (float *)&P 行也可能是对齐违规。对齐规则和严格别名规则是完全独立的规则,不应相互混淆。 (一些写得不好的页面试图将严格的别名“解释”为某种对齐要求)。

关于c - 为什么转换不同的指针类型会导致 TBAA(基于类型的别名分析)违规?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34074496/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com