首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >reinterpret_cast、char*和未定义的行为

reinterpret_cast、char*和未定义的行为
EN

Stack Overflow用户
提问于 2016-09-10 18:51:30
回答 1查看 3.8K关注 0票数 19

在什么情况下,reinterpret_castchar* (或char[N])是未定义的行为,以及何时定义了行为?我应该用什么经验法则来回答这个问题?

正如我们从this question中学到的,以下是未定义的行为:

代码语言:javascript
复制
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

但是,在什么时候,我们可以对一个reinterpret_cast数组执行一个char,并且它不是一个未定义的行为?以下是几个简单的例子:

  1. 没有new,只有reinterpret_cast: (Int) char datasizeof(int);*reinterpret_cast(data) = 42;//第一个强制写入UB?int I=*reinterpret_cast(数据);//读取如何?*reinterpret_cast(数据)= 4;//第二次写入如何?int j=*reinterpret_cast(数据);//或二读? int的生存期什么时候开始?这是与data的声明吗?如果是,data的生存期什么时候结束?
  2. 如果data是一个指针呢? data_ptr =新字符(Int);*reinterpret_cast(data_ptr) = 4;//这是UB吗?int I= *reinterpret_cast(data_ptr);//读取如何?
  3. 如果我只是在线路上接收结构,并希望根据第一个字节的情况有条件地转换它们,该怎么办? //用于处理这些类型的成员的句柄函数(MsgType1 const& );void句柄(MsgTypeF const& );char buffer100;:recv(some_socket,buffer,100)开关(缓冲区){ case '1':句柄(*reinterpret_cast(缓冲区));//是否是UB?中断;大小写'F':句柄(*reinterpret_cast(缓冲区));中断;// .}

这些案件中有UB吗?都是吗?这个问题的答案在C++11和C++1z之间有变化吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-11 01:59:01

这里有两个规则:

  1. rule/8,也就是严格的混叠规则:简单地说,您不能通过指针/引用访问一个对象。
  2. type /8:简单地说,如果您为不同类型的对象重用存储,那么如果不首先对旧对象进行清洗,就不能使用指向旧对象的指针。

这些规则是区分“内存位置”或“存储区域”和“对象”的重要部分。

您的所有代码示例都会遇到相同的问题:它们不是您将它们投射到的对象:

对齐(Int)焦炭数据;

它创建类型为char[sizeof(int)]的对象。该对象不是int。因此,您可能不会像访问它一样访问它。不管是读还是写,你还是激怒了UB。

同样:

char* data_ptr =新字符(Int);

它还创建了一个类型为char[sizeof(int)]的对象。

char buffer100;

这将创建一个类型为char[100]的对象。该对象既不是MsgType1也不是MsgTypeF。因此,您不能访问它,就好像它是。

请注意,这里的UB是作为Msg*类型之一访问缓冲区的时候,而不是在检查第一个字节时。如果您的所有Msg*类型都是微不足道的可复制的,那么完全可以接受读取第一个字节,然后将缓冲区复制到适当类型的对象中。

代码语言:javascript
复制
switch (buffer[0]) {
case '1':
    {
        MsgType1 msg;
        memcpy(&msg, buffer, sizeof(MsgType1));
        handle(msg);
    }
    break;
case 'F':
    {
        MsgTypeF msg;
        memcpy(&msg, buffer, sizeof(MsgTypeF));
        handle(msg);
    }
    break;
// ...
}

请注意,我们讨论的是语言状态将是什么未定义的行为。编译器可以很好地处理其中的任何一个。

这个问题的答案在C++11和C++1z之间有变化吗?

自从C++11 (特别是basic.life)以来,已经有了一些重要的规则澄清。但规则背后的意图并没有改变。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39429476

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档