第19讲:自定义类型:结构体

本文详细介绍了C语言中结构体的声明、变量创建与初始化、赋值、成员访问以及内存对齐规则。特别关注了匿名结构体、typedef的应用,以及内存对齐的必要性和如何调整默认对齐数以优化性能。
摘要由CSDN通过智能技术生成

1.结构体类型的声明

2.结构体变量的创建和初始化

3.结构体变量的赋值

4.结构体成员访问操作符

5.结构体内存对齐

1.结构体类型的声明

1.1结构体声明

struct 结构体名称

{

        结构体成员...

}

举例:描述一个学生:

2结构体变量的创建和初始化

2.1匿名结构体类型

匿名结构体就是在声明时不给结构体取名字,这样的类型只能在结构体声明时顺便创建变量,在不使用关键字typedef时是不能在其他地方进行结构体变量的定义的。

这里对a的初始化不是必须的, 可以只定义结构体变量a。

2.2匿名结构体搭配typedef

这时候就可以用typedef所创造的别名实现结构体变量的定义了。

2.3结构体的自引用

在结构体中不能包含类型为自己本生的成员

在struct stu类型里放着一个struct stu类型的成员b,那么成员b里面又有一个类型为struct stu的成员变量,如此下去,就像套娃一样,永远走不到尽头。(结构体变量是可以不完全初始化的,这里不是因为未初始化成员变量b所导致的错误)

但是,结构体声明中允许有自身类型所对应的指针类型的成员变量。

那么,这里可以用匿名结构体吗?

答案是不可以的!!!

我们用typedef试试:

这是因为声明的优先级高于typedef,这里的stu是对前面这个结构体声明的取别名。

所以,最好是把名字取好。

3.结构体变量的赋值

使用花括号依次赋值

4.结构体成员访问操作符

方法一:用点号对结构体变量的成员变量进行访问。

方法二:用->通过结构体变量的指针对结构体变量的成员进行访问。

5.结构体内存对齐

5.1对齐规则

1.结构体的第一个成员对齐到结构体变量起始位置偏移量为0的位置

2.其他成员要对齐到对齐数的整数倍的地址处

对齐数=编译器默认对齐数和成员变量中较小的一个

vs的默认对齐数是8

linux中gcc没有默认对齐数,对齐数就是成员自身的大小

3.结构体总大小为最大对齐数(每个成员都有一个对齐数,取当中最大的)的整数倍

4.如果结构体1内嵌套了结构体2,那么结构体2的对齐数是结构体2成员变量中最大的对齐数,结构体1的总大小是所有最大对齐数(包含被嵌套的结构体成员)的整数倍。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
struct stu
{
	char c1;
	int i;
	char c2;
};
int main()
{
	printf("%zd", sizeof(struct stu));
	return 0;
}

c1的大小是1,默认对齐数是8,所以c1的对齐数是1,现占用1字节

i的大小是4,默认对齐数是8,所以i的对齐数是4,为了对齐,先浪费3个字节,再分配4个字节,现占用8字节

c2的大小是1,默认对齐数是8,所以c1的对齐数是1,已经对齐,不需要浪费空间,分配一个字节,现在占用9字节

最大对齐数为4,为了对齐,需再浪费3个空间,共12字节

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
struct stu
{
	char c1;
	char c2;
	int i;
	
};
int main()
{
	printf("%zd", sizeof(struct stu));
	return 0;
}

8个字节

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
struct stu
{
	double d;
	char c;
	int i;
	
};
int main()
{
	printf("%zd", sizeof(struct stu));
	return 0;
}

16个字节

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
struct stu
{
	double d;
	char c;
	int i;
	
};
struct s
{
	char c1;
	struct stu a;
	double d;
};
int main()
{
	printf("%zd", sizeof(struct s));
	return 0;
}

32个字节

5.2为什么存在内存对齐

1.不是所有硬件都能任意访问任意地址上的任意数据的,某些硬件只能在某些地址处取某些特定类型的数据。

2.对齐后的数据基本只需一次就能完成访问,假设处理器一次取8个字节,则开始取的位置必须是8的整数倍,如果能保证所有的double类型的数据地址都对齐到8的整数倍,那么这样的double类型的数据只需一次就能取出。

总的来说:内存对齐是一种空间换时间的操作

在声明结构体的时候,尽量让小的成员聚在一起,从而使用零碎的空间,在节省时间的前提下,尽量节省空间。

5.3修改默认对齐数

#pragma pack()//括号里写新的默认对齐数

#pragma pack()//括号里什么都不写,恢复默认对齐数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

INUYACHA

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

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

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

打赏作者

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

抵扣说明:

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

余额充值