黑马程序员-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. (*指针变量名).成员名
  2. 指针变量名->成员名

代码实现:

 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. 结构体类型定义里可以有其他结构体类型,比如:
     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行代码

  2. 结构体类型名是可以省略的(不推荐使用),不过一般这种情况下结构体变量一起定义的,否则没法使用该类型的结构体,比如:
    1 //定义一个Student类型的结构体
    2 struct {
    3     int age; //年龄
    4     float weight; //体重
    5     char *name; //姓名
    6 } stu; //结构体变量名为stu

    第2行代码struct后面没有跟上类型名,第6行代码stu为结构体变量名,如果没有这个变量名,下次想用这种结构体类型的话,还得重新写一遍结构体类型定义,是非常麻烦的,所以一般不建议这样用

  3. 结构体初始化整体赋值时是不能和定义分开的:
     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";

     

  4. 结构体变量的分配空间问题:首先只定义结构体类型,系统是不会分配内存空间的,只有出现了结构体变量的时候,系统才会分配一定大小的内存空间给变量,分配的原则是按照内存对齐原则,具体细节请参照:结构体的内存空间分配原理

 

posted @ 2015-04-08 19:25  大_智  阅读(155)  评论(0编辑  收藏  举报