gpt4 book ai didi

c++ - C/C++ 严格别名、对象生命周期和现代编译器

转载 作者:IT王子 更新时间:2023-10-28 23:35:48 25 4
gpt4 key购买 nike

我对 C++ 严格别名规则及其可能的影响感到困惑。考虑以下代码:

int main() {
int32_t a = 5;
float* f = (float*)(&a);
*f = 1.0f;

int32_t b = a; // Probably not well-defined?
float g = *f; // What about this?
}

查看 C++ 规范,第 3.10.10 节,从技术上讲,给定的代码似乎都没有违反那里给出的“别名规则”:

If a program attempts to access the stored value of an object through an lvalue of other than one of the following types the behavior is undefined:
... a list of qualified accessor types ...

  • *f = 1.0f; 不会违反规则,因为无法访问 存储的值,即我只是通过指针写入内存。我不是从内存中读取或试图在这里解释一个值。
  • int32_t b = a; 行没有违反规则,因为我是通过它的原始类型访问的。
  • float g = *f; 行并没有因为同样的原因违反规则。

another thread , 成员 CortAmmon 实际上在响应中提出了相同的观点,并补充说,通过写入 事件对象 产生的任何可能的未定义行为,如 *f = 1.0f;,将由标准的“对象生命周期”定义来解释(这对于 POD 类型来说似乎微不足道)。

但是:互联网上有大量的证据表明上述代码将在现代编译器上产生 UB。见 herehere例如。
大多数情况下的论点是编译器可以自由地将 &af 视为彼此没有别名,因此可以自由地重新调度指令。

现在最大的问题是,这种编译器行为是否真的是对标准的“过度解释”。
该标准唯一一次专门讨论“别名”是在 3.10.10 的脚注中,其中明确指出这些是管理别名的规则。
正如我之前提到的,我没有看到任何上述代码违反标准,但很多人(可能还有编译器人员)会认为它是非法的。

我真的很感谢您在此处进行澄清。

小更新:
正如成员 BenVoigt 正确指出的那样,在某些平台上,int32_t 可能与 float 不一致,因此给定的代码可能违反了“存储足够对齐和大小”的规则。我想说的是,在大多数平台上,故意选择 int32_t 以与 float 对齐,并且这个问题的假设是类型确实对齐。

小更新#2:
正如几位成员所指出的,int32_t b = a; 行可能违反了标准,尽管不能绝对肯定。我同意这一观点,并且在不改变问题的任何方面的情况下,请读者从我上面的声明中排除该行,即没有任何代码违反标准。

最佳答案

你的第三个要点错了(也许第一个也是)。

您声明“float g = *f; 行并没有出于同样的原因违反规则。”,其中“同样的原因”(有点模糊)似乎是指到“通过其原始类型访问”。但这不是你在做什么。您正在通过 float 类型的左值(从表达式 *f 获得)访问 int32_t(名为 a) >)。所以你违反了标准。

我也相信(但不太确定)存储一个值是对(那个)存储值的访问,所以即使 *f = 1.0f; 也违反了规则。

关于c++ - C/C++ 严格别名、对象生命周期和现代编译器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18659427/

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