本篇文章主要是对结构体数据类型的一个知识扩展,包含了结构体的嵌套使用、结构体数组、结构体指针。

简述结构体的定义与使用(构造类型结构体的知识扩展)(1)

1. 构造体的嵌套使用

在学习结构体时,有提到结构体里面的成员可以是基本数据类型,也可以是数组、结构体等其他类型。

那么,接下来就说一下,在定义结构体中嵌套另一个结构体的两种方法。

第一种方法:独立结构嵌套。

分别定义了两个结构,然后将其中一个结构嵌套在另一个结构中。

struct Birthday{ int dd; int mm; int yy; }; struct Student{ char *name; struct Birthday birthday; };

这里需要注意两个点:

A. 嵌套的结构体(Birthday)必须要在被嵌套的结构体(Student)之前定义,如果顺序反了,编译器是不会通过的,会给出如下报错。

error: field 'birthday' has incomplete type

错误:字段'birthday'的类型是不完整的

这是因为C语言程序的编译是自上而下执行的。

如果两个结构体的顺序写反了,编译器首先是执行到 Student 结构,看到里面的 Birthday 结构声明的变量,因为结构体是程序员自定义的数据类型,系统是不提供的,而这里的 Birthday 结构还没有进行定义,所以C语言是不认识这种数据类型,就会给出报错。

B. 在定义结构中嵌套另一个结构,如果没有定义结构的别名,struct 和结构名称必须同时出现,才表示为结构体类型。

同时在结构体中,一个完整的成员必须包含类型以及变量名,缺一不可。

第二种方法:嵌入式嵌套

这种方式就不用考虑两个独立结构谁先谁后的问题,只需要在被嵌套的结构(Student)中以嵌入的方式定义嵌套的结构(Birthday)类型。

struct Student{ char *name; struct Birthday{ int dd; int mm; int yy; } birthday; };

和前面的独立结构嵌套相比,如果嵌套的结构体比较少,可以采用这种方式。但是要嵌套好几个结构体,建议还是使用独立嵌套的方式,否则会导致代码看上比较冗长复杂。

嵌套结构体的初始化和访问方式如下:

// 变量初始化 Struct Student s1 = {"张三", {1,1, 2000}}; // 访问 Birthday 结构中 dd 成员; s1.birthday.dd; // 1

关于结构体嵌套,还有一个非常重要的问题:所定义的结构体能将自身类型作为成员吗?

struct A{ struct A a; } aa;

答案是不能的,像上面这种写法是错误的。

嵌套的是定义结构自身的变量,就会出现这种情况:aa.a.a.a.a.a.a……就会一直无限循环下去。

在内存分配的时候,由于无法确定所定义的结构体地长度,就不会被系统允许。

但是如果想要引用自身,也不是不行,可以通过指针来进行使用。

指针类型,无论是什么类型的指针,所占的内存大小都是固定的。

struct A{ struct A *a; } aa;

2. 结构体指针

结构体的指针类型的声明方式如下:

struct 结构名称 *变量名;

结构体的指针声明和基本数据类型是一样,都需要带上寻址运算符(&)。

struct Student{ char *name; int age; }; struct Student s1 = {"张三", 15}; struct Student *ps1 = &s1;

通过指针类型访问结构体中的成员的方式有两种。

第一种,通过访问运算符。

(*ps1).name; // 张三

由于访问运算符的优先级比较高,所以需要对 *ps1 添加上括号。

如果没有加上括号,先执行的是 ps1.name,而 ps1 是一个指针变量,所存储的是结构体 s1 的内存地址。

第二种方式,通过箭头运算符 -> 进行访问。

箭头运算符是C语言结构体的一种特殊的运算符,可以直接从结构体指针变量中访问结构体里面的成员。

ps1->age; // 15

3. 结构体数组

数组,是用来存储相同类型的集合。

结构体数组,用来存储同一个结构类型的不同数据,也叫作结构的集合。

例如,定义了一个学生的结构,而一个班里面又有很多个学生。总不能一个一个地去声明不同数据的学生结构类型,这样做就是显得太麻烦了。

这时候,我们就可以用一个数组变量来存储起来。

结构体数组的定义方式如下:

struct Student{ char *name; int age; } class[5] = { {"孙悟空", 500}; {"唐僧", 33}; {"猪八戒", 101}; {"沙僧", 98}; {"白龙马", 102}; };

定义的结构体数组变量 class 中括号里面的数字,如果有进行初始化操作,即数组中全部元素都已经赋值,则可以不用带。系统会自动根据数组里面的内容,给该数组确定相应的长度。

如果没有进行初始化,则必须要带上数组长度,否则就会出错。

结构体数组的访问方式也比较简单,通过数组索引值取出相应的结构,再通过访问运算符进行访问。

例如:我们想知道唐僧的年龄。

class[1].age; // 33

总结

以上就是关于构造数据类型,结构体的知识扩展内容,包括了嵌套使用、结构体指针以及结构体数组的知识。

,