【发布时间】:2022-02-08 05:09:04
【问题描述】:
取以下代码:
char chars[4] = {0x5B, 0x5B, 0x5B, 0x5B};
int* b = (int*) &chars[0];
(int*) &chars[0] 值将在循环(长循环)中使用。在我的代码中使用 (int*) &chars[0] 而不是 b 有什么优势吗?创建b 是否有任何开销?由于我只想将其用作别名并提高代码可读性。
另外,只要我知道自己在做什么,就可以进行这种类型转换吗?或者我应该总是memcpy() 到另一个具有正确类型的数组并使用它?我会遇到任何未定义的行为吗?因为在我目前的测试中,它是有效的,但我看到人们不鼓励这种类型转换。
【问题讨论】:
-
你可能会发现godbolt.org很有用
-
现代编译器几乎优化了你能想到的一切。如果有帮助,一个临时变量肯定会被优化掉。相反,多次使用的表达式很可能只计算一次并缓存在寄存器中,就好像您已将其分配给临时变量(公共子表达式消除)。因此,无论您编写哪种方式,您都可能会得到相同的代码;因此,只需选择更清晰的。
-
您的代码中没有分配。只有初始化(
=s 不是赋值)。无论如何,当您深入到机器指令级别时,初始化变量的简单类型转换(如您的示例中所示)都是免费操作。在您的情况下,编译器可以识别&chars[0]是一个有效的内存地址,并且通常只会使用相同的值初始化b(类型对编译器很重要,而不是机器指令)。使用这些变量的后续代码可能具有未定义的行为。 [此外,测试不能证明不存在未定义的行为]。 -
顺便说一句,在这个例子中,你为什么还要费心从数组中转换呢?
int x = 0x5b5b5b5b; int *b = &x;更短,避免了严格的别名问题,而且这个值甚至与字节序无关。 -
我不确定演员表是否有严格的别名问题,但如果确实如此,那么
memcpy会修复它,并且一个体面的编译器也可以优化 memcpy,所以它不会有额外的费用。在 C++20 中,可能有一种方法可以用bit_cast代替。
标签: c++ optimization strict-aliasing