我想重写一段(旧)代码以符合标准。旧代码使用缓冲区来存储POD结构和校验和,以通过网络发送它并接收它。对于发送,代码如下:
struct MessageStruct {int a; float b;};
char buffer[sizeof(MessageStruct) + sizeof(uint32_t)];
((MessageStruct*)buffer)->a = 12;
((MessageStruct*)buffer)->b = 3.14159f;
*((uint32_t*)(buffer + sizeof(MessageStruct))) = 9876;
// Use the data buffer in some way.
SendMessage(buffer, sizeof(buffer));
对于接收,代码如下:
struct MessageStruct {int a; float b;};
// Receive: char *buffer, int size
const MessageStruct *message = (MessageStruct*)buffer;
uint32_t checksum = *((uint32_t*)(buffer + sizeof(MessageStruct)));
如何更新此代码以使其完全符合标准投诉,尤其是不违反严格的别名规则?
我找到了解决类似问题的帖子:strict aliasing and alignment,Shared memory buffers in C++ without violating strict aliasing rules。然而,这些都没有真正回答我的问题;或许他们这样做,但后来我没有看到它。
更新:正如一些答案已经说明的那样,最简单的方法是使用memcpy
。我想知道,有没有办法使用placement new或其他构造来消除复制和构建就地的需要?
答案 0 :(得分:2)
在您的情况下,避免违反严格别名规则的最简单方法是将memcpy()填充到缓冲区中。
答案 1 :(得分:1)
使用memcpy
:
MessageStruct msg;
msg.a = 12;
msg.b = 3.14;
uint32_t n = 9876;
memcpy(buffer, &msg, sizeof(msg));
memcpy(buffer + sizeof(msg), &n, sizeof(n));
答案 2 :(得分:1)
首先,您将结构的内存中表示形式发送到不同计算机的方法存在缺陷,因为其他计算机可能具有与您的不同的布局或大小。使用正确定义的元格式,如JSON,XML或类似的东西。
现在,如果你不关心这些缺陷,你可以采取更进一步的方法:
struct MessageStructWithChecksum:
MessageStruct
{
uint32_t checksum;
};
除struct
和原始字节之间的转换外,没有别名问题。另请注意,您可以定义函数本地结构,并且可以编写模板以用于不同的消息类型。
答案 3 :(得分:1)
发送部分最简单:
struct MessageStruct {int a; float b;};
struct MessageStructWithCheckSum { MessageStruct s; uint32_t check_sum;};
MessageStructWithCheckSum m;
m.s.a = 12;
m.s.b = 3.14159f;
m.check_sum = 9876;
// Use the data buffer in some way.
SendMessage(reinterpret_cast<const unsigned char*>(m), sizeof(m));
您可以通过[..] char或unsigned char类型访问对象的存储值。
对于阅读部分,我认为您必须复制以避免严格的别名规则。
但事实上,你必须做一些特殊的处理才能管理字节序(以及具有不同表现形式的类型),无论如何这都是一种复制。