关于结构体的认识

目录

1.结构体的类型

2.结构体的在内存中的储存

3.为什么会存在内存对齐呢?

4.位段


1.结构体的类型

结构体是C语言中可以自定义的数据类型,它可以包含多个不同类型的成员变量,这些变量会同时储存在内存中,可以使用它来表示一个实体的属性或者一组相关的数据。

定义它的关键字是struct,后面跟着可以自定义的名称和括号,在括号中可以定义成员变量的类型和大小,每一个变量由类型和名称组成,用分号分隔。在结尾括号的分号前可以自定义添加结构体变量。

结构体示例:

在示例中,我们定义了一个名字为student的结构体,它有三个成员变量name,age和gender,它们分别表示名字,年龄,性别。

结构体可以通过使用 . 运算符来进行访问成员变量。

注意:只有在定义结构体student结尾括号的分号前定义的结构体变量是全局变量,其他则是局部变量

这里我定义了一个结构体局部变量S同时自定义成员变量,通过使用 .运算符我成功将年龄打印了出来。

注意:如果进行了结构体变量的地址传参,那么就不再使用 .运算符进行访问成员变量,需要使用->来进行访问成员变量

2.结构体的在内存中的储存

在前面创建的结构体student,它的大小是多少呢?

这里结构体在内存中的存储是连续的一块空间,在结构体储存时会出现内存对齐,但为什么结构体student的大小是12呢?

首先得了解内存对齐的规则:

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

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

对齐数:编译器默认的一个对齐数与该变量成员大小的较小值,如果没有默认对齐数,对齐数就是成员自己的大小

3.结构体的总大小是最大对齐数的整数倍。

4.如果嵌套了结构体的话,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,

结构体的整体大小就是所有最大对齐数(包含嵌套的结构体中的成员的对齐数)的整数倍。

如图:

char name为一个字节对齐到0的位置,但后面的int age是四个字节那么就会浪费3个字节到4的位置,此时4为int四个字节的倍数所以int age从4的位置开始储存,char gender大小也1字节所以直接存入8的位置即可,此时结构体变量S一共使用了9个字节,但9并不是最大对齐数4的倍数,此时会再浪费三个字节到11的位置上,此时一共使用了12个字节为4的倍数,所以结构体变量S总大小为12个字节。

如果想要节省空间,可以优先将字节数小的成员放在前面。

3.为什么会存在内存对齐呢?

1.不同平台的原因(移植原因)

有的硬件平台不能够随意访问地址上的数据,只能访问特定地方的数据,否则会出现错误

2.性能原因

数据结构应该尽量向自然边界上对齐,因为在访问未对齐的内存,处理器需要进行两次内存访问,而对齐的内存访问只需要一次。设一个处理器总是从内存中读取4个字节,则地址必须是4的倍数,如果我们能够保证所有int类型的数据的地址都对齐为4的倍数,那么就可以进行单次读取,不会出现一个对象放在两个4个字节的内存块中需要读取两次的情况。

总体来说:结构体的内存对齐是将空间浪费来换取时间的做法。

4.位段

结构体能够实现位段自定义结构体成员的大小的能力,位段的声明如下:

1.位段的成员必须是int,unsigned int或者signed int类型或者char类型

2.位段的成员需要在结构体成员变量后面加上一个冒号和数字

位段的内存分配注意事项:

1.位段的空间分配是以一个字节(char)或者四个字节(int)的方式进行开辟

2.它进行自定义大小是以bit位来定义大小

位段能够自定义结构体成员的大小如图:

这里将他们自定义为1,2,4个bit位加起来并未超过8个bit位,所以得出大小为1个字节

将2,10,5转换为二进制为0010,1010,0101,此时会发现P1的分配的空间不够出现截断,它只能存下低位0,P2只能存入10,P3倒是没什么事,由此可见在使用位段时应该注意赋予值的大小。

注意:

1.如果自定义的大小已经将第1个字节填至不够剩余成员的大小,则浪费第一个字节内的剩余空间存入第二个字节。

2.由上面的图可以看出位段有着许多的不确定因素,如果注重移植性应该避免使用位段

3.位段在内存中的储存并没有准确的方向,这里我是从右到左,实际也有可能是从左到右


感谢你能够读到这里,希望本篇文章对你有帮助。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值