自定义类型:结构体、枚举、联合(一)

本文详细介绍了结构体的创建、使用及内存对齐等概念,并探讨了结构体与基本数据类型的区别,以及如何通过位段提高存储效率。

结构体:

1、结构体类型的创建:

补充一点:结构体内部的变量赋不赋值都可以。

2、不完全声明结构体(省略掉结构体标签的结构体)的创建:

 匿名结构体和结构体的区别是:

1、省略掉了结构体标签

2、结构体变量的创建就只有下图这一种方式,这也就意味着,如果你想使用该结构体,则在创建结构体时一定也要写上结构体变量,否则你就没法使用该结构体。

3、创建的结构体的类型与其他结构体的类型不会相同:

 两个结构体的即使成员相同,但是仍不是同一类型。

 3、结构体类型和int、double等类型的区别:

1、结构体类型需要先创建再使用,而int、double等可以直接使用。

2、结构体类型的书写方式为:struct student,而整形、浮点型的书写方式为:int  、double

注释:这里为了方便理解,将结构体标签写为student。结构体标签是在创建结构体时定义的。

4、结构的自引用:

通过在结构体内添加该结构体的指针实现结构体的自引用。

如果写成 下图这样 系统会报错。

原因:如果计算机处理器是32位时,指针大小为4byte,计算机处理器是64位时,指针大小是8byte,在固定的处理器中,指针大小是确定的。但是如果直接在结构体中直接自引用,该结构体的大小是无法确定的,这会使系统崩溃。

5、结构体变量的定义和初始化:(同一标签的结构体只能定义一次)

第一种:

第二种:

 

 第三种:

 

初始化:

 在这里我要额外补充一种结构体成员的赋值:数组

第一种方式是对数组直接初始化,第二种是对结构体初始化,此时如果用{}将数组中的元素括起来时,如果元素个数不足数组会自动补0,如果不用{},数组会自动获取元素,直到数组被填满,才会到下一个成员。(结构体中的成员赋值和初始化时如果都不用{}分割开,则只有第一个成员被填满才会轮到下一个成员)第三种方式,就是使用循环:

补充:在结构体中初始化数组时一定要在[]中写明元素个数,否则系统会报错。

6、结构体内存对齐:

在讲结构体内存对齐前我们先来看两个结构体:

 

 为什么同一个结构体,只是成员的排序不同,他们所占的空间大小却截然不同呢?

这是因为结构体在内存中存储时需要进行内存对齐。

内存对齐规则:

对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS中默认的值为8

1、第一个成员存放起点在与结构体偏移量为零的位置

 2、第二个成员放在第一个成员后面,存放起点为对齐数的整数倍

3、结构体总大小为所有成员中最大对齐数的整数倍。

4、结构体的总偏移量必须是它最大成员字节数的整数倍(包括嵌套的结构体中的最大成员)。如果一个结构体B里嵌套另一个结构体A,结构体A的对齐数就是A中所有成员的对齐数的最大值,存放起点为对齐数的倍数,结构体A所占空间大小为A的大小。(例如:struct B里存有struct A,A里有char,int,double等成员,那A的对齐数是8,存放起点就是8的倍数)。

内存对齐参考资料:(16条消息) c语言结构体嵌套的对齐方式_binbinyantai的博客-优快云博客_结构体嵌套结构体怎么对齐

为了方便读者理解,我再通过作图向大家展示:

 存储方式:

    虽然用了9个字节就已经将数据存储完了,但是由于此时结构体总大小,不是结构体成员中最大对齐数4的整数倍,所以仍旧会向下偏移,一直偏移到第12个格子。

结构体为什么要使用内存对齐?

为了提高程序运行效率。 

如何即减少空间损耗,又提高运行效率?

在创建结构体时,将占用空间小的放在一起。

7、如何修改编译器默认对齐数?

可以使用#pragma pack()函数,使用前:

 

 使用后:

8、结构体传参:

 上述两种方式中,如果直接传结构体,系统需要为重新开辟一些空间,接收传过来的结构体。如果结构体较大,会产生空间浪费,通过地址传递,可以避免不必要的空间浪费。

位段

位段的用处:

能够将int、unsigned int、signed int、char型变量(整形家族都可以)在内存中所占空间的大小由字节级改为bit级。

如何使用位段?

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

 使用位段时确保结构体中所有变量的类型都相同,因为当结构体中所有变量类型相同时,结构体

存储时就不会浪费字节。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值