0
点赞
收藏
分享

微信扫一扫

【Linux冯诺依曼体系结构】

JamFF 2024-04-19 阅读 33

大家好,今天和大家分享C语言结构体有关的知识,感谢大家观阅,记得三连支持一下哦!

b32e726f087d4b7987af82fec5be7954.jpeg

一、结构体的概念

我们知道在C语言中有许多的内置类型,如int、char、float等等,但是仅仅只有这些内置类型是完全不够的我们所有问题的,比如:描述⼀个学⽣需要名字、年龄、学号、⾝⾼、体重等。C语⾔为了解决这个问题,增加了结构体这种⾃定义的数据类型,让程序员可以⾃⼰创造适合的类型。

二、结构的声明

假如我们要声明一个描述学生的结构体变量:

c5c1ac16beb54751bc50ce806b78ba59.png

显然这个结构体有4个成员。通常结构体的声明在main函数的外面,也就是在全局中。

结构的特殊声明:

我们在声明结构的时候,可以不完全的声明。
如:

a50b1717e3c545b38fd97b7baf111b39.png8324586a1ccb4223acfa51b66cbdcf39.png

这种结构体只能使用一次被叫做——匿名结构体。

注意:

typedef 对结构体类型重命名:

结构体在声明完之后,我们用起来每次都要在前面加struct,这就十分的麻烦,有什么办法把它的变的和普通类型一样用的方便呢?typedef。如:

6338f6cd7f834269b1566291c7fe0c92.png

这样我们就可以使用简短的名字了。并且对匿名结构体进行重命名,匿名结构体就可以使用多次了。

三、结构体变量的定义和初始化

1.结构体变量的定义

结构体变量的创建其实和普通变量的定义是一样的。

如:172b99949f004713a442c67e9185526c.png

与普通变量不同的是要在前面加一个struct。

2.结构体变量的初始化

结构体变量的初始化有点类似于数组,我们直接来看例子:ca7900faa37146c78bf9ce0c72d60eba.png

这种方法是按照结构体成员一个一个进行初始化的。

0b17392c268b4558a30fe913d09f412d.png

这种方法是不按照顺序来初始化的。

四、结构的⾃引⽤

结构的⾃引⽤,顾名思义就是,结构体成员中包含结构体类型。

比如我们定义一个链表的节点:

5164e5089b8e44c6ac87d56d1112a748.png

我们可以看到上面的代码是错误的那是为什么呢?

其实,我们在声明这个结构体到next时,并没有完全声明完,⼀个结构体中再包含⼀个同类型的结构体变量,这样结构体变量的⼤⼩就会⽆穷的⼤,是不合理的,所以这里报了错。

正确的是要改成指针的形式,如:0e99a79e1a34492faec8f1dd3e9cb0da.png

在结构体⾃引⽤使⽤的过程中,夹杂了 typedef 对匿名结构体类型重命名,也容易引⼊问题,如:
4280493e54e041f59d8b2f411cccdbd1.png

我们可以看到这里出现错误。因为Node是对前⾯的结构体类型的重命名产⽣的,但是在结构体内部提前使⽤Node类型来创建成员变量,这是不⾏的。所以在结构体中自引用中我们要写完整。(包括匿名结构体中)。0041825c362c454f98c1d1b7038560da.png

五、结构体内存对⻬

我们知道内置类型是有大小的如:int大小是4个字节。那么结构体大小是多少呢?

b807fa2ff63a47229010e928abb89ed2.png

我们可以看到结构体也是有大小的,但是我们发现上面两个结构体成员是一样的,只是顺序不一样,大小却不一样,这是为什么呢?这是因为结构体大小是要计算的,下面我们就介绍如何计算结构体的大小.

1.对⻬规则

在学习如何计算结构体的大小之前我们需要了解一个知识——结构体内存对⻬规则

下面我们看一些例子:847a8e9418734548851d6a6b7cdbbeac.png

f79d567f106c4e9cb9437832d14dc525.png

上面就是结构体A和结构体B大小不一样的原因。下面我们再来看一下难一点的:c1fbe7171f0748aba1a839e6e29f852c.png

我们可以看到这是一个结构体嵌套的类型,那么它的大小怎么求呢?我们来看:

6df1c48fc61344b5a29830e9bb97348e.png

好了以上就是结构体大小的计算方式了,为什么要这样计算呢?

2.为什么存在内存对⻬?

大多数解释有两个原因:

总的来说:就是拿空间来换取时间的做法。
所以我们在设计结构体的时候让占⽤空间⼩的成员尽量集中在⼀起,这样就既满⾜对⻬,⼜节省空间了。就如上面两个结构体A和B一样。

3.修改默认对⻬数

默认对齐数也是可以修改的。#pragma 这个预处理指令,可以改变编译器的默认对⻬数。

如:

231f60f9d7154f1ea104a0143d3a5b02.png

如果我们将默认对齐数改为1,那么该结构体大小就是两个char类型和一个int类型,一共是6个字节。

e179b9f2b6c0430d8e79532f55a4ac20.png

六、结构体传参

8530e0195f59438ab1daa69a3148a84f.png

我们可以看到上面结构体传参有传值和传址,那么它们哪一个好呢?这里优先推荐传址

因为:

所以:结构体传参的时候,要传结构体的地址。

七、结构体实现位段

下面我们来了解一下结构体实现位段的能力。

1.什么是位段

通俗来讲,位段就是改变了成员变量大小的结构体。

位段的声明和结构是类似的,有两个不同:
1. 位段的成员必须是 int、unsigned int 或signed int ,在C99中位段成员的类型也可以选择其他类型。
2. 位段的成员名后边有⼀个冒号和⼀个数字

如:

861af1c9341c4398a5ad3bc37b40acea.png475898a48b0e4bcbba77f6319f9de74b.png

上面A就是一个位段类型,里面的成员大小被改变了。在这里是直接改成比特位而不是字节。下面我们来看看这个位段的大小。32538e6b32c94828a02be8045bdff270.png

我们可以看到是4个字节。那么位段在内存中是怎么存储的呢?下面我们就要讲讲位段的内存分配了.

2.位段的内存分配

前面我们提到位段成员是按比特位来存储的,由于在不同的编译器是存储的方式不同,所以位段的存储方式不同。如:6038b07deacd44269b7b692d05db6f16.png

下面我们就来看看在VS环境下位段是怎样存储的。

b7ddc0ee2d5a4541a02dfeea3aad43b5.png

00b4a77c95f84cdb9b3f9acf79dfd971.png

我们可以看到在VS环境中确实是按照我们假设的这样来存储位段的,但是在其他环境下就不一定是这样了

3.位段的跨平台问题

位段的移植性是很差的。

所以:跟结构相⽐,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。

位段使用注意事项:

好了以上就是本篇文章的全部内容了,感谢大家的观看,创作不易,三连支持一下吧!

812dd1a160274e53b45d2b148cd7ba71.gif

举报

相关推荐

0 条评论