当询问C中常见的未定义行为时,灵魂比我提到的严格别名规则更加开明.
他们在说什么?
我一直在寻找,但找不到明确的答案.
很多人说使用工会来打字 - 双关语是不明确的和不好的做法.为什么是这样?考虑到你写入原始信息的内存并不仅仅是自己的改变,我看不出为什么它会做任何未定义的任何原因(除非它超出了堆栈的范围,但这不是一个联合问题,这将是糟糕的设计).
人们引用严格的别名规则,但在我看来,就像说你不能这样做,因为你做不到.
如果不打双关语,联盟的意义又是什么呢?我在某个地方看到它们应该被用来在不同的时间使用相同的内存位置来获取不同的信息,但为什么不在再次使用之前删除信息呢?
总结一下:
额外信息:我主要使用的是C++,但想了解它和C.特别是我正在使用工会在浮点数和原始十六进制之间进行转换以通过CAN总线发送.
很长一段时间我都是reinterpret_cast这样使用的:
static_assert(sizeof(int) == sizeof(float));
int a = 1;
float b = *reinterpret_cast<float*>(&a); // viewed as float in binary.
Run Code Online (Sandbox Code Playgroud)
然而,当我最近回顾C++中的类型转换时,我发现当考虑严格的别名规则时,它是UB!可以优化对初始数据的不同类型(或者确切地说,非相似类型)的指针的引用。(我知道std::bit_cast在 C++20 中这是另一种方法。)
从我的角度来看,reinterpret_cast主要是用于指针类型转换。然而,考虑到禁止取消引用,我如何使用另一种类型的指针?
我浏览了何时使用reinterpret_cast,下面引用了一个答案:
需要reinterpret_cast 的一种情况是与不透明数据类型交互时。这种情况经常发生在程序员无法控制的供应商 API 中。下面是一个人为的示例,其中供应商提供了用于存储和检索任意全局数据的 API。
但是当涉及到这些API的实现时,如果要在那里使用数据,就很难避免取消对指针的引用。
看起来只有转换为另一种指针类型并返回初始指针类型才是合理的(但这有什么意义?为什么不使用初始类型或直接定义模板?)。所以我的问题是:什么时候使用reinterpret_cast而不违反该规则?有没有通用的用法?
我真的是 C++ 的新手,所以任何建议将不胜感激。
#include <iostream>
class c1{
};
class c2{
};
int main(){
c1 a;
c2 b;
//b = static_cast<c2>(a); <-- will not compile
b = *reinterpret_cast<c2*>(&a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
b = static_cast<c2>(a); 不会编译出现此错误:
no matching conversion for static_cast from 'c1' to 'c2'
Run Code Online (Sandbox Code Playgroud)
使用reinterpret_cast和做 abit cast是实现这一目标的唯一方法吗?