结构体字节对齐

Posted 旧年不在666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了结构体字节对齐相关的知识,希望对你有一定的参考价值。

结构体字节对齐

一、为什么需要字节对齐?

  • 总的来说,字节对齐的目的是为了提高数据的读写效率。例如有的硬件平台要求数据的起始地址必须从偶数开始,如果数据被放在了计数地址,读写的时候就需要耗费两个总线周期,而存放在偶数地址的只需要一个总线周期就可以。

二、如何改变默认的字节对齐方式?

  • 结构体内存对齐字节可以通过#pragma pack(n) 的方式来指定
#pragma pack(4)			//强制4字节对齐
struct C
{
    double d;
    char b;
    int a;
    short c;
};

#pragma pack()			//恢复默认的对齐方式

struct B
{
    double d;
    char b;
    int a;
    short c;
};
  • #pragma pack() 能够取消自定义的对齐方式,恢复默认对齐
  • #pragma pack(push) 和#pragma pack(pop) 的问题
#pragma pack(push)		//编译器编译到此处时将保存对齐状态(保存的是push指令之前的对齐状态)
#pragma pack(4)

struct CC
{
    double d;
    char b;
    int a;
    short c;
};

#pragma pack(pop)		//编译器编译到此处时将恢复push指令前保存的对齐状态(请在使用该预处理命令之前使用#pragma pack(push))

struct BB
{
    double d;
    char b;
    int a;
    short c;
};
  • #pragma pack() 取消自定义对齐方式,恢复默认方式,而push之后pop是回到push指令之前的对齐方式
  • #pragma pack(show)
以警告信息的形式显示当前字节对齐的值
  • #pragma pack(push, n)
先将当前字节对齐值压入编译栈栈顶,然后再将 n 设为当前值
  • #pragma pack(pop, n)
将编译栈栈顶的字节对齐值弹出,然后丢弃,再将 n 设为当前值
  • #pragma pack(push, identifier)
将当前字节对齐值压入编译栈栈顶,然后将栈中保存该值的位置标识为 identifier
  • #pragma pack(pop, identifier)
将编译栈栈中标识为 identifier 位置的值弹出,并将其设为当前值。注意,如果栈中所标识的位置之上还有值,那会先被弹出并丢弃
  • #pragma pack(push, identifier, n)
将当前字节对齐值压入编译栈栈顶,然后将栈中保存该值的位置标识为 identifier,再将 n 设为当前值
  • #pragma pack(pop, identifier, n)
将编译栈栈中标识为 identifier 位置的值弹出,然后丢弃,再将 n 设为当前值。注意,如果栈中所标识的位置之上还有值,那会先被弹出并丢弃。

注意:如果在栈中没有找到 pop 中的标识符,则编译器忽略该指令,而且不会弹出任何值

以上是关于结构体字节对齐的主要内容,如果未能解决你的问题,请参考以下文章

结构体字节对齐问题探究

C语言结构体字节对齐

c语言结构体字节对齐详解

关于字节对齐的理解

结构体嵌套联合体字节对齐问题

字节对齐-------结构体共用体