【发布时间】:2018-08-02 11:22:10
【问题描述】:
我的程序通过网络接收消息。这些消息被一些中间件反序列化(即我无法更改的其他人的代码)。我的程序接收到如下所示的对象:
struct Message {
int msg_type;
std::vector<uint8_t> payload;
};
通过检查msg_type,我可以确定消息负载实际上是一个uint16_t 值数组。我想在没有不必要的副本的情况下读取该数组。
我的第一个想法是这样做:
const uint16_t* a = reinterpret_cast<uint16_t*>(msg.payload.data());
但是从a 读取似乎违反了标准。这是第 3.10.10 条:
如果程序尝试通过以下类型之一以外的左值访问对象的存储值,则行为未定义:
- 对象的动态类型,
- 对象动态类型的 cv 限定版本,
- 与对象的动态类型类似(如 4.4 中定义)的类型,
- 对应于对象动态类型的有符号或无符号类型,
- 一种有符号或无符号类型,对应于对象动态类型的 cv 限定版本,
- 一种聚合或联合类型,在其元素或非静态数据成员(递归地包括子聚合或包含联合的元素或非静态数据成员)中包含上述类型之一,
- 一种类型,它是对象动态类型的(可能是 cv 限定的)基类类型,
char或unsigned char类型。
在这种情况下,a 将是泛左值,uint16_t* 似乎不符合任何列出的条件。
那么如何将有效负载视为uint16_t 值的数组而不调用未定义的行为或执行不必要的复制?
【问题讨论】:
-
你不需要处理字节顺序吗?
-
这将改善问题,以准确显示消息的内容,而不是“类似”。 (我的回答假设完全一样)
-
提示:你如何确保
payload.data()满足uint16_t[]的对齐要求? -
@M.M 我不同意:这是一个相对常见的问题——至少,我在不同的项目中遇到过多次——所以我抽象了问题的本质。提供其中一种消息类型的完整副本只会掩盖这一点。
-
@Jarod42 根据字节序提供两种不同的选项是有意义的:一个带有字节序不匹配的副本;以及它们匹配的非复制选项。至少,如果这个问题的答案不只是“你不走运”,它会这样。
标签: c++