c语言 结构体大小的计算与位段(vc6.0)

结构体大小的计算

一:在没有嵌套的情况下:

1.结构体的第一个成员变量放在结构体在内存中存储位置的0偏移处开始
2.从第二个成员往后的所有成员,都放在一个对齐数(成员的大小和默认对齐数的较小值)的整数倍的地址处
3.结构体的总大小是结构体的所有成员的对齐数中的最大的那个对齐数的整数倍

举几个简单的例子:

​
struct stu{
	int a;
	char b;
	int c;
};

/*  struct stu
[0][1][2][3] | [4][5][6][7] | [8][9][10][11]
[a][a][a][a] | [b][ ][ ][ ] | [c][c][c ][ c]
*/

struct stu1{
	char a1;
	char b1;
	int c1;
};

/*  struct stu1
[0 ][1 ][2][3] | [4 ][5 ][6 ][7 ] | [8][9][10][11]
[a1][b1][ ][ ] | [c1][c1][c1][c1] | [ ][ ][ ] [  ] 
*/

​

可以看出stu大小为1,stu1大小为8

二:在嵌套了结构体的情况下:

如果嵌套了结构体的情况,嵌套的结构体对齐的自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(包含嵌套结构体的对齐数)的整数倍

举个简单的例子

​
struct stu2{
	char a2;
	struct stu b2;  //stu最大对齐数为4,所以在内存中[4]的位置开始存放
	int c2;
};

/*  struct str2
[0 ][1][2][3] | [4 ][5 ][6 ][7 ] | [8 ][9 ][10][11] | [12][13][14][15] | [16][17][18][19] 
[a2][ ][ ][ ] | [b2][b2][b2][b2] | [b2][b2][b2][b2] | [b2][b2][b2][b2] | [c2][c2][c2][c2] 
*/

​

可以看出stu2大小为20

三:修改默认对齐数

修改默认对齐数用#pragma pack()

举个简单的例子:

#pragma pack(1)//修改默认对齐数
struct stu3{
	double a3;
	int b3;
	char c3;
};
#pragma pack()//取消修改

/*  struct stu3
[0 ][1 ][2 ][3 ] | [4 ][5 ][6 ][7 ] | [8 ][9 ][10][11] | [12]
[a2][a2][a2][a2] | [a2][a2][a2][a2] | [b2][b2][b2][b2] | [c2]
*/

可以看出stu3大小为13

位段

1.位段的成员必须是int,unsigned int,signed int,char。
2.位段的空间上是按照需要以4个字节(int)或者一个字节(char)的方式来开辟的
3.位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段

举个简单的例子:

struct stu4{
	int a:2;
	int b:4;
	int c:10;
	int d:20;
};

对于以上位段,int型,先开辟四个字节

/*
	[0000 0000][0000 0000][0000 0000][0000 0000]
*/

计算总元素大小:2(bit)+4(bit)+10(bit)+20(bit)=36(bit)

4字节空间不够,再开辟4个字节,8个字节总大小为64bit,够用了,所以stu4的大小为8个字节.

接下来看看位段中的元素如何存储:

struct stu5{
	char a:2;
	char b:4;
	char c:6;
	char d:8;  
};

首先我们知道一个char类型大小为1个字节,1个字节为8bit,stu5中的元素总大小为20bit,所以需要开辟3个字节(24bit)。

接下来给位段赋值:

struct stu5{
	char a:2;
	char b:4;
	char c:6;
	char d:8;  
}s={2,5,10,11};

数据如何存储呢?不妨先把内存表示出来

[0000 0000][0000 0000][0000 0000]

首先存储顺序无非就两种情况:高位开始或者低位开始

假设从低位开始存储,那么第一个字节存储完a,b之后应该是一下情况:

[00 0101 10]

那么还剩下两个bit,是舍弃还是存c呢?我们先假设舍弃,那么s存储完之后应该是一下情况:

[00 0101 10][00 001010][00001011]

转换成16进制应该是:

[16 0a 0b]

我们再vc6.0中编写代码查看内存:

 完全正确。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值