一图看懂结构体对齐

为什么需要结构体对齐?根本原因在于CPU访问数据的效率问题

  • 不是所有的硬件平台都能访问任意地址的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据的,否则抛出异常。
  • 数据结构(尤其是栈)应尽可能在自然边界上对齐,因为在访问为对齐的内存时,处理器需要访问多次,而对齐的内存处理器只需要访问一次。

对齐原则

  • 以 #pragma pack(x) 中 x 的大小和结构中占用空间最大的成员做比较,取小值为 n(外对齐依据)
  • 以 n 值和结构体每个成员比较,得出结果列表为 m[x]
  • 根据每个成员的大小依次向内存中填充数据,要求填充 成员的起始地址 减去 构体起始地址 的差都可以整除 m[x] ,如不能整除则向后移动,直到可以整除再填充成员到内存(内对齐依据)
  • 当全部成员填充完毕后所占用的字节若不能整除 n,则扩充内存到可以整除 n 为止。
#include <stdio.h> 
#pragma pack(4)
typedef struct data {
char a;
short b;
int c;
} DATA, *PDATA;

int main(int argc, char* argv[])
{
printf("sizeof(DATA) = %lu\n", sizeof(DATA)); return 0;
}

一图看懂结构体对齐_#pragma

#include <stdio.h>

#pragma pack(8)

typedef struct data
{
char a;
double b;
int c;
} DATA, *PDATA;

int main(int argc, char* argv[])
{
printf("sizeof(DATA) = %lu\n", sizeof(DATA));
return 0;
}

一图看懂结构体对齐_嵌入式_02

上面是比较严谨的理解,画图的话最简单。

struct A{
int a; // 4
char b; // 1
short c;// 2
};

struct B{
char b;
int a;
short c;
};

#pragma pack(2) // 指定对齐字节
struct C{
char b;
int a;
short c;
};
#pragma pack() // ,取消指定字节对齐,恢复缺省字节对齐

int main(int argc, char **argv)
{
printf("sizeof(A):%zd\n", sizeof(struct A));
printf("sizeof(B):%zd\n", sizeof(struct B));
printf("sizeof(C):%zd\n", sizeof(struct C));

return 0;
}

A结构体【8字节】

a

a

a

a

b

c

c

B结构体【12字节】

b

a

a

a

a

c

c

C结构体【8字节】

b

a

a

a

a

c

c

结构体对齐在嵌入式软件编程中很重要,要引起足够重视,希望对你有所帮助。

一图看懂结构体对齐_整除_03