如何在内存中布置具有不同对齐的嵌套结构?

时间:2014-10-29 22:01:38

标签: c++ structure memory-alignment

我是一名C#开发人员,为用C ++编写的服务器编写客户端。服务器通过TCP / IP将一些任意数据流式传输到客户端,我们必须在另一端重新组装它。服务器首先向我们发送数据描述,然后是数据本身。

问题结构:

struct Inner_S
{
  double a;
  double b[4][4];
};

#pragma pack(1)
struct Packed_S
{
  uint8_t c;
  Inner_S d;
};

服务器告诉客户端外部结构的对齐方式为1,内部结构的对齐方式为8.协议规范说明:

  

流式结构中字段的对齐是根据Itanium 64位C ++应用程序二进制接口规范(即与典型64位平台上的典型GNU编译器相同)完成的。

我找到了Itanium 64-bit C++ Application Binary Interface specification。我认为我正在寻找的部分是“除了虚拟基地之外的成员分配”,但我迷失在那里。

在C#端,我正在读取数据流并使用从结构中提取的值打包我自己的类。我需要知道流中的确切位置,以查找结构的每个元素。

我目前正在以这种方式处理结构,根据我的用户说这是错误的:

(以对齐1开始结构)(不需要填充)(读取简单值)c(以对齐8开始内部结构)(向对齐8添加填充)0000000(读取字段)aaaaaaaa(开始数组)(读取简单值) )BBBBBBBB .....

at least one site.

支持该方法

所以,当我解析这些数据时,如何处理Inner_S中的对齐?

caaaaaaaabbbbbbbb ....(我想?) caaaaaaaa0000000bbbbbbbb ....(看起来不对)

1 个答案:

答案 0 :(得分:6)

正如@Cameron所建议的那样,我尝试使用offsetof,因为这涉及到POD类型。

#include <iostream>
#include <cstddef>
#include <cstdint>
using namespace std;

struct Inner_S
{
  double a;
  double b[4][4];
};

#pragma pack(1)
struct Packed_S
{
  uint8_t c;
  Inner_S d;
};

int main() {
    cout << "Size: " << sizeof(Packed_S) << endl;
    cout << "c offset: " << offsetof(Packed_S, c) << endl;
    cout << "d offset: " << offsetof(Packed_S, d) << endl;
    cout << "a offset: " << offsetof(Packed_S, d.a) << endl;
    cout << "b offset: " << offsetof(Packed_S, d.b) << endl;
    return 0;
}

输出

Size: 137
c offset: 0
d offset: 1
a offset: 1
b offset: 9

因此,使用您的符号将结构打包为caaaaaaaabbbbbbbb....。请注意,如果取出#pragma pack(1)指令,编译器会在c之后添加3个字节的填充。

See here