一、如何知道当前计算机的字节个数
#include <stdio.h>
int main(void)
{
printf("The bytes of the variables in this machine are:\n");
printf("char: %d byte\n",sizeof(char));
printf("short: %d bytes\n",sizeof(short));
printf("int: %d bytes\n",sizeof(int));
printf("long: %d bytes\n",sizeof(long));
printf("float: %d bytes\n",sizeof(float));
printf("double: %d bytes\n",sizeof(double));
printf("long long : %d bytes\n",sizeof(long long ));
printf("long double: %d bytes\n",sizeof(long double));
}
编译运行,在目标机运行一下,就知道不同数据类型占几个字节
long形占用8个自己,由此也知道此计算机是64位系统,32位系统,long是4字节。
二、结构体对齐的意义
cpu执行一条指令,是按4字节取的,地址空间必须是4的倍数,如下
如下图,假如一个int整形变量,存放在0x02-0x06的地址,那么读取变量a时,需要先读取0x00,再读一次0x04,才能把a的数据读出来,增加了一次指令,那么性能降低一半,所以意义,就是增加执行效率,一次性把int型数据读出来
三、结构体字节对齐计算规则
1、测试1
按图中结构体,成员中最大是int型4字节,所以是4的倍数,char a 需要填充3个无效字节,char c 需要3个字节。
2、测试2
看图中,是64位操作系统,long型是8个字节,先看结构体1,最大是4,按4的倍数填充。结构体2是是按8的倍数填充,为什么
char g是填充3个呢,因为结构体1最大是4,按规则3,结构体h起始地址是4的倍数,所以变量g,也是按4的倍数填充,写个测试
程序如下,结果是对的
程序运行结果
做个修改,把结构体1的b换成long型,发现结构体2变成了56,因为变量g,需要按8字节对齐了。
程序运行结果
4、测试4,结构体1b变成short型,则按2的倍数算,结构体2 char g 则是按2的倍数来计算
运行结果
5、测试5,联合体,结构体嵌套联合体
运行结果
联合体是8个字节,因为只按最大字节的变量,分配一个公用地址。所以结构体2大小是40字节
6、测试6,内嵌枚举
gcc的规则,枚举无论多少个,都是一个常量,int型,4个字节,
总结,内嵌结构体时,按除结构体外,其他成员,最大数据类型整数倍对齐,内嵌的结构体,起始地址,需要内嵌结构体整数倍,或最大成员整数倍 ,比如char g变量,是内嵌结构体上面相邻位置,是内嵌结构体的起始地址,所以要结合变量结构体h,来计算。
六、设置成不对齐,或按需要对齐
#pragma pack(4)
结构体1按字节对齐后是24,结构2按2个字节对齐是40,
设置成不对齐,不填充,是多少个就是多少个
七、内嵌数组
运行结果是28,按int4个字节对齐
再修改下,把数组改成char型
运行结果是12个,
那是怎么对齐的呢,仍然按int4个字节对齐,char a需要结合b数组,a+b前面3个,后面两个填充2个。
运行结果是7个,嘿,想不通为啥,没法解释。