内存对齐与内存开辟。结构体(struct),位段,枚举类型(enum),联合体(union)。

1.结构体内存对齐

(1)结构体内存对齐规则

a.第一个成员在与结构体变量偏移量为0的地址处

b.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处

对齐数=编译器默认对齐数与该成员大小的较小值.

vs中默认值为8(如果没有默认对齐数 则默认对齐数为成员大小本身)

c.结构体总大小为最大对齐数的整数倍

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

(2)举例:

a.

int main()
{
	struct S1
	{
		char c1;  //1 8 对齐数为1  1字节
		int i;    //4 8 对齐数为4 要在偏移量4的整数倍处开辟 浪费3个字节 8字节
		char c2;  //1 8 对齐数为1  9字节 最后结构体大小要为最大对齐数4的整数倍 所以又浪费3字节 12字节
	};
	struct S1 s;
}

b.

#include<stdio.h>
int main()
{
	struct S2
	{
		char c1;//1 8 对齐数为1 1字节
		char c2;//1 8 对齐数为1 2字节
		int i;  //4 8 对齐数为4 要在偏移量为对齐数的整数倍处开辟 浪费两个字节 8字节
	};
	struct S2 s;
}

c.

int main()
{
	struct S3
	{
		double d;// 8 8 对齐数为8 8字节
		char c;  // 1 8 对齐数为1 9字节
		int  i;  // 4 8 对齐数为4 在12处开辟 16字节
	};
	struct S3 s;
}

d.

int main()
{
	struct S3
	{
		double d;// 8 8 对齐数为8 8字节
		char c;  // 1 8 对齐数为1 9字节
		int  i;  // 4 8 对齐数为4 在12处开辟 16字节
	};
	struct S4
	{
		char c1;     //1 8 对齐数为1 1字节
		struct S3 s3;//8 8 嵌套结构体对齐数为内结构体的最大对齐数8 在8处开辟8+16=24
		double d;    //8 8 对齐数为8 8+24=32 32字节 结构体大小为最大对齐数的整数倍
	};
	struct S4 s;
	
}

(3)内存对齐的原因

a.平台原因(移植原因)

不是所有的硬件平台都能访问任意地址上的任意数据。

b.性能原因

为了访问未对齐的内存,处理器要做两次内存访问。而对齐后的内存,处理器只需要访问一次。

(4)总结

如果要使结构体尽可能少的浪费空间,我们需要让占用空间小的成员尽量集中在一起。

2.位段

1.什么是位段?

位段的声明和结构体是类似的,用两个不同:

a.位段的成员必须是:int ,unsigned int,signed int,char , unsigned char。

b.位段的成员名后边有一个冒号和一个数字。

int main()
{
	struct A
	{
		int _a : 2; //_a这个成员只占2个bit位 只能表示0 1 2 3
		int _b : 5; //_b这个成员只占5个bit位
		int _c : 10;
		int _d : 30;
	};
}

2.位段的空间是按照需要以4个字节或一个字节来开辟的

3.弊端:位段是不跨平台的.

3.枚举(一一列举)

利用枚举类型定义常量(比宏定义有优点)

int main()
{
	enum Color
	{
		RED = 5,
		GREEN = 8,
		BULE
	};          //一次可以定义多个常量
}

4.联合(共用体)

这些成员共用一块空间(同一时间只能使用一个!)

int main()
{
	union Un
	{
		char c;//c用的是i的第一个字节的空间
		int i; 
	};
	union Un un; //联合体大小至少是最大成员的大小
}

1.联合体的大小(要对齐)

int main()
{
	union Un
	{
		short arr[7];// 14 2 
		int i;//4   4  
    }u;//本来14个一节就够了 但是联合体需要对其 
	    //到最大对齐数4的整数倍 所以为 16个字节
}

2.利用联合体判断大小端

#include<stdio.h>
int main()
{
	union Un
	{
		char c;
		int i;
	}u;
	u.i = 1;
	if (u.c == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
}

  • 53
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 99
    评论
评论 99
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sessy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值