什么是字节对齐
计算机存储的基本单位是字节(byte)
,但在读写内存的时候,我们并非一个字节一个字节的读取,而是2,4,8的倍数来读取,所以就对基本数据类型的地址做出了一些限制,它的地址也必须是2,4,8的倍数。那么数据类型就需要按照一些规则在空间上进行排列,这样就产生对齐。
对齐原则
- 规则1:结构体变量的首地址能够被其对齐字节数大小所整除
- 规则2:结构体每个成员相对结构体首地址的偏移都是成员大小的整数倍,如不满足,对前一个成员填充字节以满足
- 规则3:结构体的总大小为结构体对最大成员大小的整数倍,如不满足,最后填充字节以满足
测试案例
#include <iostream>
using namespace std;
struct T1
{
int m1;
char m2;
int m3;
short m4;
};
struct T2
{
char a;
char b;
};
struct T3
{
char a;
char b;
int c;
};
struct T4
{
char a;
char b;
char c;
char d;
char e;
int f;
};
struct Person
{
char name[10];
int age;
char sex;
float score;
};
void test01()
{
cout<<sizeof(struct T1)<<endl;
}
void test02()
{
cout<<sizeof(struct T2)<<endl;
}
void test03()
{
cout<<sizeof(struct T3)<<endl;
}
void test04()
{
cout<<sizeof(struct T4)<<endl;
}
void test05()
{
cout<<sizeof(struct Person)<<endl;
}
int main(void)
{
test01();
test02();
test03();
test04();
test05();
return 0;
}
T1
0~3 | 4 | 5~7 | 8~11 | 12~13 | 14~15 |
---|
m1 | m2 | 填充 | m3 | m4 | 填充 |
- m3 成员变量相对结构体首地址的偏移量不是sizeof(int),也就是不是成员大小的整数倍,故前面成员填充满足,走到起始地址为8
- 最后的填充依据规则3,结构体整个的地址是最大成员大小的整数倍,后面14~15填充
T2
T3
T4
T5
0 | 1 | 2 | 3 |
---|
name[0] | name[1] | name[2] | name[3] |
4 | 5 | 6 | 7 |
---|
name[4] | name[5] | name[6] | name[7] |
T6
struct s1
{
short a;
long b;
};
struct s2
{
char c;
struct s1 d;
long long e;
};
sizeof(s1)--->16
sizeof(s2)--->32
offsetof宏的使用
#include <stdio.h>
#include <stddef.h>
typedef struct Person
{
char name[10];
int age;
char sex;
}PERSON;
int main(void)
{
printf("name = %lu\n",offsetof(PERSON,name)) ;
printf("age = %lu\n",offsetof(PERSON,age));
printf("sex = %lu\n",offsetof(PERSON,sex));
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/742e23d32d41513bbeb19a8f6f2b7089.png)
字节对齐实际应用
合适的设计可以节省空间
struct T2
{
int m1;
char m2;
short m4;
int m3;
};
sizeof(struct T2) --->12
跨平台通信- 可以指定字节对齐的字节数
#pragma pack(1)
struct T1
{
int m1;
char m2;
int m3;
short m4;
};
#pragma pack()
sizeof(struct T1) --->11
struct T2
{
int m1;
char m2;
int m3;
short m4;
}__attribute__((packed));
sizeof(struct T2) ---> 11
struct T3
{
int m1;
char m2;
char r1[3];
int m3;
short m4;
char r2[2];
};