讲解下struct和union的内存求值和对齐
以题目讲解
结构体联合体sizeof内存求值 - 对齐数
- 不同位数下类型字节大小
- 内存对齐规则
- struct 内存对齐求值
- 嵌套struct内存对齐求值
- union的内存大小求值
- union大小计算准则
- struct嵌套union内存对齐求值
不同位数下类型字节大小
一定要搞清楚编辑器,一般编辑器中的类型字节如图:
类型 | 16位平台 | 32位平台 | 64位平台 |
char | 1个字节 | 1个字节 | 1个字节 |
short | 2个字节 | 2个字节 | 2个字节 |
int | 2个字节 | 4个字节 | 4个字节 |
unsigned int | 2个字节 | 4个字节 | 4个字节 |
float | 4个字节 | 4个字节 | 4个字节 |
double | 8个字节 | 8个字节 | 8个字节 |
long | 4个字节 | 4个字节 | 8个字节 |
long long | 8个字节 | 8个字节 | 8个字节 |
unsigned long | 4个字节 | 4个字节 | 8个字节 |
指针 | 2个字节 | 4个字节 | 8个字节 |
一般我使用的是64位的编译器,下面来看看对齐规则
内存对齐规则
规则
- 结构体的第一个成员直接对齐到相对于结构体变量起始位置为
0
处偏移。 - 从第二个成员开始,要对齐到某个【对齐数】的整数倍的偏移处。
- 结构体的总大小,必须是最大对齐数的整数倍。每个结构体成员都有一个对齐数,其中
最大的对齐数就是最大对齐数
。 - 如果嵌套了结构体的情况。嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
struct 内存对齐求值
- 举例:struct内存求值
#include <stdio.h>
#pragma pack(16)
struct BBB {
long num;
char ha;
short ba[5];
}b;
int main() {
printf("%d\n", sizeof(b.num));//8
printf("%d\n", sizeof(b.ha)); //1
printf("%d\n", sizeof(b.ba)); //10 ,short大小是2
//最大对齐数是8
printf("%d\n", sizeof(BBB));
return 0;
}
//这里ba数组的最大对齐数是2,因为short大小2小于定义的对齐数16
//sizeof(BBB)=8+1+1+(2*5)=20,这里的1是为了让ba数组对齐到2的倍数
//但是对齐规则里面有个结构体的总大小,必须是最大对齐数的整数倍
//这里最大对齐数是8,也就是结果需要是8的倍数,最终等于sizeof(BBB)=24
嵌套struct内存对齐求值
- 如果有嵌套结构体呢 :
#include <stdio.h>
#pragma pack(16)
struct BBB {
long num;
char ha;
short ba[5];
struct BBB2
{
int s; //4
int ba2[5]; //20
char ha2[2]; //2
}b2; //4+20+2=26。对齐=4的倍数=28
}b;
int main() {
printf("%d\n", sizeof(b.num));//8
printf("%d\n", sizeof(b.ha)); //1
printf("%d\n", sizeof(b.ba)); //10 ,short大小是2
printf("%d\n",sizeof(b.b2));//28,见上面
//最大对齐数是8
printf("%d\n", sizeof(BBB));
return 0;
}
//sizeof(BBB)=8+1+1+(2*5)=20,后面嵌套的BBB2最大对齐数是4,对齐大小是28,所以从4的倍数出发,这里是20开始,正好,sizeof(BBB)=20+28=48,正好是8的倍数
union的内存大小求值
解释下union的内存大小求值
union大小计算准则
1、至少要容纳最大的成员变量
2、必须是所有成员变量类型大小的整数倍 —— 记住是成员变量类型 char c[7]算 1
- 举例:求sizeof(union)
#include<stdio.h>
//联合体
union u2
{
char a; //1
int b; //4
short c; //2
double d; //8
int e[5]; //20
}U3;
//主函数
int main(){
printf("%d\n",sizeof(U3));//输出24
return 0;
}
struct嵌套union内存对齐求值
#include <stdio.h>
#pragma pack(16)
struct BBB {
int num;//4
char ch; //1
char pa[3]; //3
union {
int a; //4
float b; //4
} myUnion;//这个union内存大小等于4
}b;
int main() {
printf("%d\n", sizeof(b));
//4+1+3+4=12 ; 到char pa[3]时候这时候正好到地址8,然后union的内存是4,对齐数,要求是它的整数倍所以正好从8开始,最终结果12。满足是对齐数4,1,4的倍数
return 0;
}
其他内容见专栏的结构体和联合体的文章
如果有啥补充的后续更新