采用以下代码:
char chars[4] = {0x5B, 0x5B, 0x5B, 0x5B};
int* b = (int*) &chars[0];
(int*) &chars[0]
值将在循环(长循环)中使用。在我的代码中使用 (int*) &chars[0]
而不是 b
有什么优势吗?创建 b
是否有任何开销?因为我只想将它用作别名并提高代码可读性。
此外,只要我知道自己在做什么,就可以进行这种类型转换吗?或者我应该总是 memcpy()
到另一个具有正确类型的数组并使用它吗?我会遇到任何一种未定义的行为吗?因为到目前为止,在我的测试中,它是有效的,但我看到人们不鼓励这种类型转换。
最佳答案
is it OK to do this kind of type casting as long as I know what I'm doing?
不,这不行。 这不安全。 C++ 标准不允许这样做。您可以访问对象表示(即,将对象指针转换为 char*
),尽管结果取决于目标平台(由于 endianess 和填充)。但是,您不能安全地做相反的事情(即没有未定义的行为)。
更具体地说,int
类型可以有不同的对齐要求(通常对齐到 4 或 8 个字节)而不是 char
(不对齐) .因此,您的数组可能未对齐,并且当 b
将被取消引用时,强制转换会导致未定义的行为。请注意,它可能会导致某些处理器(例如 AFAIK、POWER)崩溃,尽管主流 x86-64 处理器支持它。此外,编译器可以假定 b
在内存中对齐 (ot alignof(int)
)。
Or should I always memcpy() to another array with the correct type and use that?
是的,或者像新的 std::bit_cast
这样的替代 C++ 操作自 C++20 起可用。不必担心性能:大多数编译器(GCC、Clang、ICC,当然还有 MSVC)会优化此类操作(称为类型双关)。
Would I encounter any kind of undefined behavior?
如前所述,是的,只要类型双关没有正确完成。有关这方面的更多信息,您可以阅读以下链接:
- What is the Strict Aliasing Rule and Why do we care?
- reinterpret_cast conversion
- Objects and alignment
because in my testing so far, it works, but I've seen people discouraging this kind of type casting.
它通常适用于 x86-64 处理器上的简单示例。但是,当您处理大代码时,编译器会执行愚蠢的优化(但对于 C++ 标准而言是完全正确的)。引用cppreference :“编译器不需要诊断未定义的行为(尽管很多简单的情况都被诊断出来),并且编译后的程序不需要做任何有意义的事情。”。此类问题很难调试,因为它们通常仅在启用优化时以及在某些特定情况下才会出现。程序的结果可能会因函数内联而改变,这取决于编译器试探法。在您的情况下,这取决于堆栈的对齐方式,堆栈对齐方式取决于编译器优化和当前范围内声明/使用的变量。一些处理器不支持未对齐的访问(例如,跨越缓存行边界的访问),这会导致数据损坏的硬件异常。
所以简而言之,到目前为止“有效”并不意味着它会随时随地有效。
The (int*) &chars[0] value is going to be used in a loop (a long loop). Is there any advantage in using (int*) &chars[0] over b in my code? Is there any overhead in creating b? Since I only want to use it as an alias and improve code readability.
假设您使用正确的方式进行类型双关(例如memcpy
),那么只要启用优化标志,优化编译器就可以完全优化此初始化。除非您发现生成的代码优化不佳,否则您不应该担心这一点。 正确性比性能更重要。
关于c++ - 现代 C++ 编译器会在类型转换后优化赋值吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70843952/