认识C语言中自定义类型:结构体与内存对齐

一、结构体

1、结构体的声明
使用关键字struct 定义:

struct  tag
	{
			number_list//成员列表
			
	}variable _list;//分号不能丢
在声明的时候,可以不完全声明,(可以省略 tag  或者variable_list)

2、结构体自引用

struct Node
	{
			int date;
			struct Node*next;
	}

3、结构体变量的定义和初始化
(1)定义结构体变量

  struct  Point
	  {
	  		int x;
	  		int y;
	  }p1;//声明类型的同时定义变量p1;
	  struct Point p2;//定义结构体变量p2;
	  struct Point p3={x,y};.//声明并初始化
 4、结构体内存对齐
(1) 当我们要计算结构体的大小时,为什么要按照结构体内存对齐规则?
举个例子:
struct P
{	
	char i;
	int b;
}x;

要访问结构体变量的成员时,需要通过(.),比如x.i ,x.b;
如果时CPU访问内存中的x.i ,x.b时,由于硬件平台的限制,会增加访问次数,画图理解一下:
在这里插入图片描述如果不内存对齐,CPU访问时,一般访问4的整数倍个字节,
访问i时,从i的起始位置访问四个字节,取出第一个字节,但是访问b时也是从i开始取4个字节,此时b 的内存还没取完,还要接着再取四个字节,将第一次提取的后三个字节和第二次提取的第一个字节合起来就是b的值,这样访问b时就多访问了一次。
如果结构体内还有更多的数据,就会让访存次数增加很多,从而影响效率。
(2),什么是内存对齐
通过牺牲空间换取效率的方案就是内存对齐,我们可以改变数据在内存中的存储方式
如图理解:
在这里插入图片描述 访问i时,访问四个字节,访问b时从i的结束,直接访问四个字节就可以得到b的内容,这样就减少了访问次数,牺牲了一部分空间,这就是内存对齐。

(3)如何内存对齐

struct S1
{
	char c1;
	int i;
	char c2;
}y;

你们觉得大小是 6个字节吗?其实他不是,是12个。

struct S2
{
	char c2;
	char c1;
	int i;
}x;

是不是觉得跟上边的结构体大小一样?不,他的大小是8,
下边讲解一下如何按照内存对齐计算结构体大小:
1)第一个成员在与结构体变量在偏移量为0的地址处。(也就是第一个成员不需要对齐)。(偏移量是相对第一个元素的位置)
2)其他成员需要对齐到某个数字(对齐数)的整数倍的地址处。
对齐:我的起始偏移量是否能整除我的对齐数。
对齐数:编译器默认的一个对齐数与该成员大小的较小值。(对齐数一般是自身的大小,一般编译器没有默认对齐数,但是可以设置)。
3)结构的总大小是最大对齐数的整数被(所有成员的的对齐数比较)
4)如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍,结构体的整体大小就是所有对齐数(包含嵌套的结构体)的整数倍。
再看这个例子:

struct S2
{
	char c2;
	char c1;
	int i;
}x;
 在内存中先放c2 (一个字节),再c1(偏移量:1)对齐数:1,可以整除,直接放(1个字节),接着放 i  ,偏移量:2,对齐数 :4

不能整除,需要将i 偏移2 个字节,占(2+4)个字节,三个总和,可以整除最大对齐数,所以总大小是8。
如图:
在这里插入图片描述
再举两个例子:
如果结构体中有数组,数组中元素大小一样,只要一个元素对齐,其他的元素都可以对齐。

int main()
{
	struct P
	{
		char g;//直接放,  占1个字节
		int i[10];//偏移量 1; 对齐数:4   占 3+4*10=43 个字节
		char h;//偏移量  44  对齐数:1  占1个字节
		double b;//偏移量 :45 对齐数:8  占3+8=11 个字节
		float c;//偏移量 56:对齐数:1     占1个字节
	}x;//总大小57 ,最大对齐数 8,不能整除8,最后的大小是64
	printf("%d", sizeof(struct P));
	return 0;
}

在这里插入图片描述
再举一个结构体自应用的例子:

int main()
{
	struct p1
	{
		char c;//1
		double f;//7+8
		int i;//4
	};//总大小20 ,最大对齐数 8,不能整除8,最后的大小是24
	struct p2
	{
		int i;//4字节
		struct p1 x;//偏移量 4:最大对齐数 8,占4+24
		double f;//偏移量 40,对齐数8,占8个字节
		short k;//偏移量 48,对齐数2,占2个字节
	};// 总大小是42 ,最大对齐数 8, 不能整除8,最后的大小是48
	printf("p1 = %d\n", sizeof(struct p1));

	printf("p2 = %d", sizeof(struct p2));
	return 0;
}

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值