结构相关知识总结
- 什么是结构?
- 结构的声明与简单使用
- 结构的初始化
- 结构中成员变量的访问
- 结构的初始化器
- 结构数组
- 结构数组的声明
- 结构数组的成员标识
- 结构的嵌套
- 结构指针
- 结构作为参数在函数中传递
- 将结构成员作为参数进行传递
- 将结构地址(指向结构的指针)作为参数进行传递
- 将整个结构作为参数进行传递
- 结构和结构指针的选择
什么是结构?
结构是一种复合类型,一个结构里面存放多种数据类型的元素,相比数组而言,简直爽歪歪不是。它既可以包含不同的数据形式,又可以使得个信息之间保持独立。
此部分非常之重要,不可马虎呀
结构的声明与简单使用
结构的声明并没有创建出实际的数据对象,只是描述了该对象是由什么组成的而已。下图中创建一个结构,结构的标识为book
,结构变量为:library
。
上图中,对于结构的创建的结构变量的声明可以合二为一,声明方法与使用方法如下图所示,而且组合之后的使用可以不要结构标记(即下图中的book可以去掉)。如果该结构模板是要多次被使用的,则需要使用结构标识。
结构的初始化
结构的初始化与数组的初始化别无二致,都是同样的手法。使用花括号将初始化列表括起来进行初始化,各个初始化项之间使用逗号隔开,为了代码的可读性,一行只写一个初始化项。使用初始化时必须要带上结构标识,不能只有结构变量与struct关键词
结构中成员变量的访问
使用结构成员运算符——点(.
)访问结构中的成员,例如上面的library.uesrID
、library.message
。值得注意的点是:library
是一个结构,但是library.uesrID
却相当于是一个int类型的变量,可以像使用其他int类型变量的情况去使用它。
例如:scanf("%d",...)
需要一个int类型的值,而library.uesrID
正符合要求的话,那么就可以这么写:scanf("%d",&library.uesrID)
,&比 . 的优先级高。
结构的初始化器
C99和C11对结构提供了指定初始化器,使用点运算符和成员名标识特定的元素,这也初始化结构的一种手段。如下图所示,可以按照任意顺序给初始化项进行赋值。
结构数组
结构数组的声明
结构数组的声明和其他类型数组的声明类似
struct book library[MAXBKS];
将library
声明成一个具有MAXBKS
个元素的数组,数组的每个元素都是一个book类型的结构变量。library[0]是第一个book类型的结构变量,library[1]是第二个book类型的结构变量,以此类推。结构数组示意图如下:
结构数组的成员标识
library[0].userID
:表示第一个数组元素与userID
相关联
library[4].mssage
:表示第五个数组元素与message
相关联
结构的嵌套
嵌套结构即在结构中包含中另一个结构,使用如下图所示,将结构数组与嵌套结构结合在了一起。
结构指针
使用结构指针的优点:指向结构的指针通常比结构本身更容易操控;结构作为参数传递的时候传递指针更有效率。
和数组不同的是,数组名是数组的地址或者说是数组首元素的地址,即有arr = &arr[0]
,但结构名不是结构的地址。
struct guy * him;
声明了一个指向struct guy
结构的指针him
.上图中那个fellow
是一个结构数组,也就是说fellow[0]
是一个结构变量,要让him
指向fellow[0]
,可以写为:him = &fellow[0],him + 1 = &fellow[1]
。
him是一个指针(struct guy类型的),是fellow[0]所在的地址,所以如果想要通过指针拿到fellow[0].income
的值,写法为:*him
,因为*him = fellow[0](因为him = &fellow[0])
,*
与&
可以相互抵掉。
fellow[0].income == (*him).income
fellow[0].handle.first = (*him).handle.first
fellow[1].handle.first = (*(him + 1)).handle.first
->运算符:
him = &fellow[0]
那么:him->income
也就是fellow[0].income
总之,如果him是指向guy类型的结构barney的指针,下列的关系恒成立。
barney.income == (*him).income == him ->income
再加一个结构指针的例子⑧。需要注意的是声明指针之后需要指向结构变量,这样才能生效。(*him).first == him ->first
结构作为参数在函数中传递
结构作为参数在函数中传递的时候既可以传递结构本身,也可以传递指向结构的指针,还可以传递结构中的成员,但前提是改成员为具有单个之的数据类型,即int、char、指针等。
将结构成员作为参数进行传递
函数并不关心被传入的参数是否为结构的成员,她只关注被传入参数是否符合相关要求的数据类型即可。
将结构地址(指向结构的指针)作为参数进行传递
sum
函数的形参列表要求传入的就是一个指针,函数在被调用的时候也传入了&DDD
,使用&
来获取结构的地址,和数组名不同,结构名只是其地址的别名。
将整个结构作为参数进行传递
此方法只适用于允许将结构作为参数的编译器,就是将【将结构地址(指向结构的指针)作为参数进行传递】中的指针换成结构就可以啦,而且几乎用的很少,所以就不再赘述啦。
结构和结构指针的选择
在设计与结构相关的函数时,选择结构或者结构指针作为参数都可以,两者各有优缺点:
指针的优点:执行起来比较快,因为只需要一个地址,而且不管是以前的C还是现在的C都适用。
指针的缺点:无法保护数据。被调函数中的某些操作可能会意外影响原来结构中的数据。
结构的优点:数据受到保护,因为函数处理的是原本数据的副本,而且代码风格也比较清晰。
结构的缺点:相较于指针而言,执行缓慢一些。