在哪些情况下将 char*
(或 char[N]
)进行 reinterpret_cast
是未定义行为,而何时是定义行为?我应该使用什么经验法则来回答这个问题?
正如我们从这个问题中学到的那样,以下是未定义行为:
alignas(int) char data[sizeof(int)];
int *myInt = new (data) int; // OK
*myInt = 34; // OK
int i = *reinterpret_cast<int*>(data); // <== UB! have to use std::launder
但是,在哪个时刻我们可以对一个char
数组进行reinterpret_cast
而不会出现未定义行为呢?以下是一些简单的例子:
没有
new
,只有reinterpret_cast
:
alignas(int) char data[sizeof(int)];
*reinterpret_cast<int*>(data) = 42; // is the first cast write UB?
int i = *reinterpret_cast<int*>(data); // how about a read?
*reinterpret_cast<int*>(data) = 4; // how about the second write?
int j = *reinterpret_cast<int*>(data); // or the second read?
int
的生命周期是从声明data
开始的吗?如果是,那么data
的生命周期何时结束?
如果data
是指针会怎样呢?
char* data_ptr = new char[sizeof(int)];
*reinterpret_cast<int*>(data_ptr) = 4; // is this UB?
int i = *reinterpret_cast<int*>(data_ptr); // how about the read?
如果我只是从网络中接收结构体,并想根据第一个字节有条件地将它们转换,该怎么办?
// bunch of handle functions that do stuff with the members of these types
void handle(MsgType1 const& );
void handle(MsgTypeF const& );
char buffer[100];
::recv(some_socket, buffer, 100)
switch (buffer[0]) {
case '1':
handle(*reinterpret_cast<MsgType1*>(buffer)); // is this UB?
break;
case 'F':
handle(*reinterpret_cast<MsgTypeF*>(buffer));
break;
// ...
}
这些情况中是否有UB?全部都是吗?这个问题的答案在C++11到C++1z之间有变化吗?
int
对象并赋值。读取该值是开始变得棘手的地方。对于**(2)也是一样(假设sizeof(int)==4
)。对于(3)**,在我看来是未定义行为。 - Igor Tandetniksizeof(int)
的假设,谢谢。 - Barrylanguage-lawyer
标签无关。 ;-] - ildjarndata
或data_ptr
上没有任何活动的int
对象。 - T.C.