#pragma pack()的用法

内存对齐

理论上,处理器可以访问处理任意地址的字节,但为了保证计算机读取的高效性,CPU会通过地址总线来访问内存。例如32位平台有32根地址线,即四个字节,所以每次就从内存读取4个字节。

为提高存储效率,编译器就会自动将一个数据尽量存放在一个步长之内,避免跨步长存储。这就是内存对齐。

结构体的存储

⾸先得掌握结构体的对⻬规则:
1. 结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处
2. 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。
对⻬数 = 编译器默认的⼀个对⻬数 与 该成员变量⼤⼩的较⼩值。
- VS 中默认的值为 8
- Linux中 gcc 没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩
3. 结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的
整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构
体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍
struct S
{
	char ch;
    int a;
    double d;
};

对于这个结构体,是从内存的低地址开始开辟空间的,首先是char类型,占一个字节,即从机构提变量起始位置开始的第一个字节是存放ch的(即偏移量为0的地方开始向后一个字节);然后是int,它是4个字节,vs默认对齐数是8,所以a要对齐到偏移量(偏移量就是从结构体变量所在内存中的起始地址开始向后数几个字节)为4的整数倍的地方。已知第一个字节已被占用,而偏移量为4 的地方没有变量,所以a存储在从偏移量为4开始向后4 个字节内(即第五个字节到第8个字节。第八个字节对应的偏移量为7)。最后是double,它要对齐到偏移量为8的整数倍的地方,即8或16 或24……而恰好从偏移量为8的地方开始就没有变量了,所以d存放在从偏移量为8的地方起向后8个字节(即第9个字节到第16个字节)。到此,已经开辟了16个字节的空间了,那么此结构体变量所占空间是否为16呢?答案是肯定的。

因为结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的 整数倍。double d 的对其书最大,是8,所以此结构体只能开辟8或16 或24……字节的大小。

struct card
{
	
	char ch;
    double d;
	int a;
};

对于这个结构体,按上述方法,ch从偏移量为0开始,而d只能从偏移量为8开始,这时已经开辟了16个字节的空间了,然后是a,它从4的倍数开始,即偏移量为16的地方,向后4个字节,这时已经20个字节了。那此变量是占20个字节吗?不是,而应该是8的倍数,即24.所以这种创建方式不如上一种创建方式好。

#pragma pack()改变默认对齐数

#pragma pack(2)是将编译器默认的对齐数改为了2,而不是原来的8.

#pragma pack()则是恢复默认对齐数

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#pragma pack(1)
struct stu
{
	int a;
	char ch;
	double d;
};
struct card
{
	
	char ch;
	int a;
	double d;
};
int main()
{
	printf("%d", sizeof(struct stu));
	printf("%d", sizeof(struct card));

	return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#pragma pack(1)
struct stu
{
	int a;
	char ch;
	double d;
};
#pragma pack()

struct card
{
	int a;
	char ch;
	double d;
};
int main()
{
	printf("%d", sizeof(struct stu));
	printf("%d", sizeof(struct card));

	return 0;
}

第一个代码结果为13  13

第二个代码结果为13  16

这就是#pragma pack()的用处

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值