【结构体详解】初始化、传参、结构体大小

结构体的创建和初始化:

常见定义方法:

1.其中A是结构体名称,a1,a2为结构体中的属性,as2是结构体对象名。

struct A
{
	int a1;
	char a2;
}as2;

2.此处为匿名结构体,结构体无名称,b1,b2为结构体中的属性,B是结构体对象名。

struct
{
	int b1;
	char b2;
}B;

3.使用typedef定义的结构体,结构体名称为C, c1,c2为结构体中的属性,没定义结构体对象。

typedef struct C
{
	float c1;
	int c2;
};

结构体的初始化:

对应上述结构体定义序号:

1.结构体对象可以在main()函数内部创建也可以在外部创建,二者的区别就是作用域不同

   如下代码中:as1只能在当前的大括号中使用,而as2的作用域是整个函数。可以理解为:

   as1类似局部变量,as2类似全局变量。

#include<stdio.h>

struct A
{
	int a1;
	char a2;
}as2;

int main()
{
	{
		struct A as1 = {10,'a'};
	}
	as2.a1;
	//as1.a1;  -- err
	return 0;
}

2.由于该结构体为匿名结构体并且已经有对象,可以直接定义,按照属性顺序赋值即可。

#include<stdio.h>

struct
{
	int b1;
	char b2;
}B;

int main()
{
	B = { 20,'b' };
	return 0;
}

3.和情况一相同。

#include<stdio.h>

typedef struct C
{
	float c1;
	int c2;
};

int main()
{
	struct C c = { 'c',1.2 };
	return 0;
}

结构体传参

法一:按照结构体成员直接传参(不推荐),如下面代码中的print1,传入a,直接采用struct A a接收

         相当于直接传值达到传参的目的。

法二:按照结构体成员指针传参(推荐),如下面代码中的print2,传入b的地址,采用struct B  *b接收

         相当于直接传地址达到传参的目的。较于上一方法,传值调用较为节省内存,且传参速度更快。为了让成员b的内容不变,可以在Struct B *b 前加 const修饰.

#include<stdio.h>

struct A
{
	int x;
	char y;
};
struct B
{
	int x;
	char y;
};

void print1(struct A a)
{
	printf("%d %c\n", a.x, a.y);
}
void print2(const struct B *b)
{
	printf("%d %c\n", b->x, b->y);
}
int main()
{
	struct A a = { 10,'a' };
	struct B b = { 20,'b' };
	print1(a);
	print2(&b);

	return 0;
}

结构体内存空间分配(内存对齐):

结构体的所占空间大小遵循对齐数规则:

结构体对齐规则:

//1.结构体的第一个成员对齐和结构体变量起始位置偏移量为0的地址处

//2.其他成员变量要对其到某个数字(对齐数)的整数的地址处,开始存放
//  对齐数 = 编译器默认对齐数(Vs中为8) 和 成员变量类型大小的 较小值

//3.结构体总大小为最大对齐数(成员属性之间)的整数倍

此处用例题来探讨内存对齐~!

例1:求结构体s1所占空间的大小
#include<stdio.h>

struct S1
{
	char c1;
	char c2;
	int a;
};


int main()
{
	struct S1 s1 = { 'a','b',100 };
	
	printf("%zd\n", sizeof(s1));

	return 0;
}

首先确定 系统默认对齐数 大小为 8,   

 c1对齐数(对应类型所占字节大小)为1,     c2对齐数为1, a对齐数为4

1.根据第一条规则,结构体的第一个成员对齐和结构体变量起始位置偏移量为0的地址处,

   c1所占大小为1个字节,地址0刚好可以存放,如图:

2.规则二:其他成员变量要对其到某个数字(对齐数)的整数的地址处,开始存放

   已知c2的对齐数为1,c1后地址为1的整数倍的是地址1,故c2存放在地址1处

    c2所占大小为1个字节,地址1刚好可以存放

3.规则二:其他成员变量要对其到某个数字(对齐数)的整数的地址处,开始存放

    已知a的对齐数为4,c2后地址为4的整数倍的是地址4,故a存放在地址4处,

    地址2、3浪费, a所占大小为4个字节在地址4向后存储4个字节直到地址7,如图:

4.从地址0-7共占8个字节,规则三:结构体总大小为最大对齐数(成员属性之间)的整数倍

   //成员属性有c1,c2,a其中最大对齐数为a:4,而所算的的8个字节是4的倍数

   故该结构体的大小为 8个字节。

例2:求结构体s2所占空间的大小
#include<stdio.h>

struct S2
{
	char c1;
	int a;
	char c2;
};

int main()
{
	struct S2 s2 = { 'a',100,'b' };

	printf("%zd\n", sizeof(s2));

	return 0;
}

首先确定 系统默认对齐数 大小为 8,   

 c1对齐数(对应类型所占字节大小)为1,     a对齐数为4, c2对齐数为1

1.根据第一条规则,结构体的第一个成员对齐和结构体变量起始位置偏移量为0的地址处,

   c1所占大小为1个字节,地址0刚好可以存放,如图:

2.规则二:其他成员变量要对其到某个数字(对齐数)的整数的地址处,开始存放

   已知a的对齐数为4,c1后地址为4的整数倍的是地址4,故a存放在地址4处,

    地址1、2、3浪费, a所占大小为4个字节在地址4向后存储4个字节直到地址7,如图:

3.已知c2的对齐数为1,a后地址为1的整数倍的是地址8,故c2存放在地址8处

    c2所占大小为1个字节,地址8刚好可以存放,如图:

4.从地址0-8共占9个字节,规则三:结构体总大小为最大对齐数(成员属性之间)的整数倍

   //成员属性有c1,c2,a其中最大对齐数为a:4,而所算的的9个字节不是是4的倍数!!!

   注意:当不满足规则三时,要在内存中申请空间,使结构体大小为最大对齐数的整数倍,而距离地             址9最近,且满足最大对齐数的整数倍的地址是 地址12

           故空间地址9、10、11、12被浪费,结构体所占内存大小为 12

//结构体的大小判断就靠这三条规则,希望同学们能够熟练应用,共勉!!!

//是不是忘了什么,你懂的!!!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值