gcc结构中的内存对齐

Mum*_*les 13 c gcc arm memory-management gcc4

我将应用程序移植到C中的ARM平台,该应用程序也在x86处理器上运行,并且必须向后兼容.

我现在有一些变量对齐的问题.我已经阅读了gcc手册,因为 __attribute__((aligned(4),packed))我解释了所说的内容,因为struct的开头与4字节边界对齐,并且由于packed语句,内部保持不变.

最初我有这个,但偶尔它与4字节边界不对齐.

typedef struct  
{  
 unsigned int code;  
 unsigned int length;  
 unsigned int seq;  
 unsigned int request;  
 unsigned char nonce[16];  
 unsigned short  crc;  
} __attribute__((packed)) CHALLENGE;
Run Code Online (Sandbox Code Playgroud)

所以我把它改成了这个.

typedef struct  
{  
 unsigned int code;  
 unsigned int length;  
 unsigned int seq;  
 unsigned int request;  
 unsigned char nonce[16];  
 unsigned short  crc;  
} __attribute__((aligned(4),packed)) CHALLENGE;
Run Code Online (Sandbox Code Playgroud)

该明白我前面所说似乎是不正确的,这两个结构是现在对齐到4字节边界,和现在的内部数据对齐到四个字节边界,但因为尾结构,该结构的大小已增加大小从42到44个字节.这个大小是至关重要的,因为我们有其他依赖于结构为42字节的应用程序.

有些人可以向我描述如何执行我需要的操作.任何帮助深表感谢.

cra*_*cot 12

如果你依赖于sizeof(yourstruct)42个字节,那么你将被一个不可移植的假设所困扰.你还没有说这是为了什么,但结构内容的字节顺序似乎很重要,所以你也可能与x86不匹配.

在这种情况下,我认为应对的唯一可靠方法是unsigned char[42]在重要的部分使用.首先编写一个精确的规范,准确说明这个42字节块中的哪些字段,以及哪个字节序,然后使用该定义编写一些代码,以便在它与可以与之交互的结构之间进行转换.代码可能是一次性序列化代码(也称为编组),或者是一堆getter和setter.


小智 5

这是为什么读取整个结构而不是成员失败的一个原因,应该避免.

在这种情况下,打包加上4对齐意味着将有两个字节的填充.发生这种情况是因为大小必须兼容才能将类型存储在一个数组中,所有项仍然对齐为4.

我想你有类似的东西:

read(fd, &obj, sizeof obj)
Run Code Online (Sandbox Code Playgroud)

因为您不想读取属于不同数据的那2个填充字节,所以必须明确指定大小:

read(fd, &obj, 42)
Run Code Online (Sandbox Code Playgroud)

您可以保持可维护性:

typedef struct {
  //...
  enum { read_size = 42 };
} __attribute__((aligned(4),packed)) CHALLENGE;

// ...

read(fd, &obj, obj.read_size)
Run Code Online (Sandbox Code Playgroud)

或者,如果您不能在C中使用C++的某些功能:

typedef struct {
  //...
} __attribute__((aligned(4),packed)) CHALLENGE;
enum { CHALLENGE_read_size = 42 };

// ...

read(fd, &obj, CHALLENGE_read_size)
Run Code Online (Sandbox Code Playgroud)

在下一次重构时,我强烈建议您单独开始阅读每个成员,这可以很容易地封装在一个函数中.