黑马程序员-C语言结构体
实际问题中的数据中往往有着不同类型的数据类型,例如在校的学生,年龄(int型)、身高(float型)、体重(float型)、姓名(字符串类型)、性别(char)等等这些都是每一个学生应有的属性,我们肯定不能用之前学过的数据类型将这些数据表达出来,结构体这种新的数据类型就应运而生,不管是C语言还是OC语言都有它的用武之地。
- 结构体是一种构造数据类型,也就是说在用之前我们必须先定义(构造)它,那么结构体的一般形式为:
1 struct 结构体名{ 2 类型1 成员名1 3 类型2 成员名2 4 ... ... 5 } 6
其中struct为关键字,是结构体类型的标志,结构体名一般首字母大写
比如定义一个学生的结构体:(注意大括号和末尾的分号)
1 struct Student{ 2 int age; 3 float weight; 4 char *name; 5 };
- 结构体类型定义完,要想使用结构体还要定义结构体变量,有些人就被这几个概念搞晕了,其实很好理解的,结构体的定义好比说明int型的数据具有哪些特点,而结构体变量的定义就类似以下语句:
1 int a;
(沿用上面的结构体)
struct Student stu;
其中stu为结构体变量名,struct Student表明stu变量为学生类型的结构体,结构体类型的定义和结构体变量的定义我们可以一步完成:
1 struct Student{ 2 int age; 3 float weight; 4 char *name; 5 }stu;
我们也可以定义多个结构体变量:
1 struct Student{ 2 int age; 3 float weight; 4 char *name; 5 }stu1, stu2, stu3;
这里的stu1、stu2、stu3都是Student类型的结构体变量
- 结构体类型变量的初始化
1 //错误代码 2 struct Student{ 3 int age; 4 float weight; 5 char *name; 6 }stu1; 7 8 stu1 = {16,58.4,"ZhangSan"};
这是初学者容易犯的错误,那么对于结构体变量的整体初始化只能是下列四种方式之一:
1 //第一种方式 2 struct Student{ 3 int age; 4 float weight; 5 char *name; 6 }stu1= {16,58.4,"ZhangSan"}; 7 8 //第二种方式 9 struct Student{ 10 int age; 11 float weight; 12 char *name; 13 }; 14 15 struct Student stu1 = {16,58.4,"ZhangSan"}; 16 17 //第三种方式 18 struct Student{ 19 int age; 20 float weight; 21 char *name; 22 }stu1 = {.weight = 58.4,.age = 16,.name = "ZhangSan"}; 23 24 //第四种方式 25 struct Student{ 26 int age; 27 float weight; 28 char *name; 29 }; 30 31 struct Student stu1 = {.weight = 58.4,.age = 16,.name = "ZhangSan"};
第一种和第二种方式要注意每个数据的先后顺序,要一一对应起来,至于第三种和第四种方式用到了访问结构体成员变量的点('.')方法,这两种方法对成语变量的赋值是可以不按顺序来
- 访问结构体的成元变量的一般形式为:结构体变量名.成员变量名(中间连接的是点号)
1 #include<stdio.h> 2 3 int main(){ 4 5 //定义一个结构体类型 6 struct Student{ 7 int age; 8 float weight; 9 char *name; 10 }; 11 //定义一个结构体变量并初始化 12 struct Student stu1 = {16,58.4,"ZhangSan"}; 13 //修改成员变量的值 14 stu1.age = 14; 15 //输出修改后的值 16 printf("%d\n", stu1.age); 17 return 0; 18 }
- 结构体数组的定义和初始化
1 #include<stdio.h> 2 3 int main(){ 4 5 //定义一个结构体类型 6 struct Student{ 7 int age; 8 float weight; 9 char *name; 10 }; 11 //定义一个结构体数组并初始化 12 struct Student stu[3] = {{16,58.4,"ZhangSan"}, 13 {15,54.3,"LiSi"}, 14 {17,55.0,"LiMing"}}; 15 //输出每个结构体数组中age的成员变量值 16 printf("%d---%d---%d\n", stu[0].age,stu[1].age,stu[2].age); 17 return 0; 18 }
- 结构体指针,因为结构体变量在内存中也有各自的存储地址,所以肯定能用指针操作
结构体变量指针的定义:
1 struct Student{ 2 int age; 3 float weight; 4 char *name; 5 }*p_stu;
也可以是这样
1 struct Student{ 2 int age; 3 float weight; 4 char *name; 5 }; 6 7 struct Student *p_stu;
那么指针式如何访问成员变量的呢?有两种方式
- (*指针变量名).成员名
- 指针变量名->成员名
代码实现:
1 #include<stdio.h> 2 3 int main(){ 4 5 //定义一个结构体类型此时内存还没有分配空间给结构体 6 struct Student{ 7 int age; 8 float weight; 9 char *name; 10 }; 11 //定义一个结构体指针,此时系统会分配相应大小的空间给指针变量 12 struct Student *p_stu; 13 14 p_stu->age = 10; 15 p_stu->name = "ZhangSan"; 16 17 printf("%d---%s\n", p_stu->age,(*p_stu).name); 18 return 0; 19 }
- 结构体的使用注意
- 结构体类型定义里可以有其他结构体类型,比如:
1 #include<stdio.h> 2 //定义一个Class类型的结构体 3 struct Class{ 4 int cla; //班级 5 int gra; //年级 6 }; 7 8 //定义一个Student类型的结构体 9 struct Student{ 10 int age; //年龄 11 float weight; //体重 12 char *name; //姓名 13 struct Class class; //Class结构体类型的变量 14 }stu; 15 16 17 //但是要注意 18 int main(){ 19 20 stu.class.cla = 7; //赋值给Class类型的成员变量cla 21 printf("%d\n",stu.class.cla); 22 23 return 0; 24 }
其中需要注意的是被嵌套的结构体(比如上面的Class结构体)定义一定要放在嵌套结构体(比如上面的Student)的前面,另外结构体的定义是可以放在main函数的前面的,这种情况下要是想访问嵌套里的成语变量,依然还是用点('.')语法,正如上面的第20行代码
- 结构体类型名是可以省略的(不推荐使用),不过一般这种情况下结构体变量一起定义的,否则没法使用该类型的结构体,比如:
1 //定义一个Student类型的结构体 2 struct { 3 int age; //年龄 4 float weight; //体重 5 char *name; //姓名 6 } stu; //结构体变量名为stu
第2行代码struct后面没有跟上类型名,第6行代码stu为结构体变量名,如果没有这个变量名,下次想用这种结构体类型的话,还得重新写一遍结构体类型定义,是非常麻烦的,所以一般不建议这样用
- 结构体初始化整体赋值时是不能和定义分开的:
1 //定义一个Student类型的结构体 2 struct Student{ 3 int age; //年龄 4 float weight; //体重 5 char *name; //姓名 6 }; 7 8 //正确写法 9 struct Student stu = {14,56.3,"ZhangSan"}; 10 11 //错误写法 12 struct Student stu; 13 stu = {14,56.3,"ZhangSan"};
结构体的整体赋值只能是这样,或者单个进行赋值:
1 //定义一个Student类型的结构体 2 struct Student{ 3 int age; //年龄 4 float weight; //体重 5 char *name; //姓名 6 }; 7 8 struct Student stu; 9 stu.age = 14; 10 stu.weight = 56.3; 11 stu.name = "ZhangSan";
- 结构体变量的分配空间问题:首先只定义结构体类型,系统是不会分配内存空间的,只有出现了结构体变量的时候,系统才会分配一定大小的内存空间给变量,分配的原则是按照内存对齐原则,具体细节请参照:结构体的内存空间分配原理