填充结构(C++)



我在C++中有一个18字节的结构。我想直接从一个文件中读取18个字节的数据到这个结构中。然而,我的C++编译器将结构填充为20字节(4字节对齐(。这对于我的编译器来说相对容易,但我更喜欢使用更可靠的跨平台/跨编译器方法。

这是结构体:

struct Test {
uint8_t a;
uint8_t b;
uint8_t c;
uint16_t d;
uint16_t e;
uint8_t f;
uint16_t g; 
uint16_t h; 
uint16_t i; 
uint16_t j; 
uint8_t  k;  
uint8_t  l;
};

我可以在结构的前面添加字节,以保证它是32字节,这在大多数系统上都是有效的对齐方式,但我不知道这是否真的适用于结构需要元素自然对齐的方式。

这方面的任何帮助都会很好,但我最终可能会手动将字节复制到属性中😔.

您有几个选项,像往常一样,您应该选择最适合您需求的选项:

  1. 如前所述,不要直接从内存中读/写,而是分别写每个字段(Java人会这样做(
    我认为这是最可移植的方法,但比后面的方法慢得多。

  2. 重新排序结构以匹配正常对齐(无论如何都是好的做法(
    在您的示例中:

struct Test {
uint8_t a;
uint8_t b;
uint8_t c;
uint8_t f; // moved
uint16_t d;
uint16_t e;
//  uint8_t f;
uint16_t g; 
uint16_t h; 
uint16_t i; 
uint16_t j; 
uint8_t  k;  
uint8_t  l;
uint16_t spare;
};

注意:它仍然有2个字节的填充,但不在中间:(

  1. 在结构上使用#pragma pack(push, 1)来告诉编译器不要对齐字节

注意:您可能需要放置多个#pragma来支持不同的编译器

#pragma pack(push, 1)
struct Test {
uint8_t a;
uint8_t b;
uint8_t c;
uint16_t d;
uint16_t e;
uint8_t f;
uint16_t g; 
uint16_t h; 
uint16_t i; 
uint16_t j; 
uint8_t  k;  
uint8_t  l;
uint16_t spare;
};
#pragma pack(pop)

我想补充一点,正确的对齐有助于CPU更快地处理,因此,您不想在所有结构上强制使用pack = 1。。。只有那些打算通过通信信道发送或接收的。

如果您是为跨平台和跨编译器编写,请忘记直接读取。只是逐字节读取。如果评测表明您需要进一步优化,可以使用底层流缓冲,也可以读取字节数组并提取每一块。

这也消除了系统端序问题。

// extract byte values
t.a = f.get();
t.b = f.get();
...
// extract a little-endian value
t.d = f.get();
t.d = t.d | (f.get() << 8);
...
// check for success or failure
if (!f) ...

通过字节数组读取块:

unsigned char buffer[ 18 ];
if (!f.read( (char *)buffer, sizeof(buffer) ))
...
t.a = buffer[0];
...
t.d = buffer[3] | (buffer[4] << 8);
...

再次,在确定存在问题之前先进行简介。

相关内容

  • 没有找到相关文章

最新更新