2015-09-25 63 views
0

我想重写一段(旧)代码以符合标准。旧代码使用缓冲区来存储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 alignmentShared memory buffers in C++ without violating strict aliasing rules。但是,这些都没有真正回答我的问题。或者他们可以,但是我没有看到它。

更新:由于一些答案已经说明,最简单的方法是使用memcpy。我想知道,有没有什么办法可以使用placement new或其他构造来否定复制和构建它的需要?

+0

@jrok嗯,好点。我会删除它。 – MicroVirus

+0

顺便说一句,你可能有endianess问题 – Jarod42

回答

2

就你而言,避免违反严格别名规则的最简单方法是将memcpy()填充到缓冲区中。

+0

感谢您的迅速回答。我也在考虑这个解决方案,但我也希望有一个避免复制的解决方案。 – MicroVirus

+0

没有标准的祝福方式。有些人会建议以工会为基础的解决方案,但这在技术上仍然是UB--尽管不是那种可能打击你的解决方案。 – SergeyA

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)); 
1

首先,你发送一个结构的内存中表示到另一台机器的非常方法是有缺陷的,因为其他机器可能有比你不同的布局,甚至大小。使用正确定义的元格式,如JSON,XML或类似的东西。从struct和原始字节,不走样的问题之间的转换

struct MessageStructWithChecksum: 
    MessageStruct 
{ 
    uint32_t checksum; 
}; 

除了:

现在,如果你只是不关心这样的缺陷,你可以把你自己的方法一步。还要注意,您可以定义函数本地结构,并且可以编写一个模板以用于不同的消息类型。

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类型访问对象的存储值。

对于阅读部分,我认为你必须复制,以避免严格的别名规则。

但事实上,你必须做特殊的处理来管理字节顺序(以及具有不同表示形式的字体),无论如何它都是一种拷贝。

相关问题