C语言允许程序员定义的数据类型主要包括结构体联合体以及枚举类型

11.2 结构体

11.2.1 结构体类型的定义

  1. struct Student_Info
  2. {
  3. char no[9];
  4. char name[20];
  5. char sex;
  6. unsigned int age,classno;
  7. float grade;
  8. };
  • struct是关键字,表示定义一个结构类型,不能省略;
  • 结构体类型名(Student_Info)必须是合法标识符,不能为关键字。可以省略,则表示无名结构体;
  • 成员数量和类型不限,可以是基本型,也可以是复杂数据类型(即结构体可以嵌套,其成员可以是另一结构体类型的变量,也可以是自身类型的指针,但不能是自身类型的变量),成员顺序也不限;
  • 整个结构体的定义必须以分号结尾

    结构体类型既然是一种数据类型标识符,则它本身是不需要占用内存单元的,只有用它来定义某个变量(实例化?)时,才会为该变量分配结构类型所需要大小的内存单元。

11.2.2 结构体变量的定义

  1. 间接定义法

    1. struct 结构体类型名
    2. {
    3. 数据类型名1 成员名1;
    4. ...
    5. 数据类型名n 成员名n;
    6. };
    7. struct 结构体类型名 变量名列表;

    可一次定义多个结构体类型变量,也可定义指向结构体类型的指针变量:

    1. struct Student_Info student1, student2;
    2. struct Student_Info *pstu;
  2. 直接定义法

与直接定义类似,只不过在定义时同时定义了结构体变量。

  1. struct 结构体类型名
  2. {
  3. 数据类型名1 成员名1;
  4. ...
  5. 数据类型名n 成员名n;
  6. } 变量名列表;

11.2.3 结构体变量的引用

非指针型结构体变量,通过成员运算符 . 逐个访问其成员:
结构体类型名.成员名

指针型结构体变量,一般是通过成员运算符 -> 逐个访问其成员,也可以用 . 运算符来访问:
结构体指针->成员名 或 (*结构体指针).成员名

  1. struct Student_Info stu;
  2. struct Student_Info *pstu;
  3. pstu=&stu; //指针pstu指向stu //或者*p=stu也可
  4. strcpy(stu.name. "zhang");
  5. pstu->grade=80;
  • 结构体变量不能整体引用,只能引用其变量成员。
  • 可以将一个结构体变量赋值给另一个结构体变量。例如: stu1=stu2 是合法的。

11.3 联合体

联合体提供了可以把几种不同类型的数据放于同一段内存的机制。这种使及各个不同的变量占用同一段内存空间的结构称为联合体。联合体的各成员相互覆盖,不能同时引用

11.3.1 类型定义

  1. union UData
  2. {
  3. short i;
  4. char ch;
  5. float f;
  6. }; //占4个字节——float
  • 联合体的内存空间大小由占据最大内存空间的成员所占的空间数决定
  • 与结构体相同,联合体定义时不分配内存单元,只有定义联合体类型变量时才会分配内存单元

    11.3.2 变量定义

    定义和引用参见结构体,与结构体相同。

    11.3.3 变量的赋值

    11.3.3.1 赋初始值

    1. union UData data = {10}; //10赋值给成员i
    2. union UData data = {'A'}; //'A'赋值给成员i,值为A的ASCII码65
    3. union UData data = {10, 'A', 12.5}; //错误,{ }中只能有一个值,且{ }不能省略
  • 联合体变量再定义时可以赋初值,但只能对第一个成员赋初值

    11.3.3.2 程序中赋值

    ```c union UData data, *p, d[10]; data = {10}; //错误 data = 10; //错误 data.i = 10; //正确 p = &data; //p指向data p->f = 12.5; //正确 d[0].ch = ‘A’; //正确

union UData data1={10}, data2; data2 = data1; //正确

  1. - 联合体变量定以后,**只能通过对其成员赋值**,不允许对整体赋值
  2. - 与结构体一样,具有相同联合体类型的变量之间可以相互赋值
  3. <a name="aJIEM"></a>
  4. ### 11.3.4 联合体的有关说明
  5. 1. 由于联合体变量的各成员共用一段内存,所以对联合体赋值后,存放的和起作用的将是最后一次存入的成员值。
  6. **一次只能用一个成员,因此以最新的为准。**
  7. 2. 对联合体变量的某个成员赋值时,也改变了其他成员的值。
  8. **联合体内的若干成员值相等(注意格式转换,如'A'转成int型就是65)。**
  9. 3. **联合体变量与其各成员的地址相同。**
  10. <a name="budgh"></a>
  11. ### 11.3.5 联合体的内存映射
  12. ![](https://cdn.nlark.com/yuque/0/2021/jpeg/10374984/1639747409731-4a1890f4-40fb-429b-a650-1ee604ea9028.jpeg)
  13. <a name="Qb0y1"></a>
  14. ## 11.4 枚举类型
  15. 枚举数据类型通常定义形式为:
  16. ```c
  17. enum 枚举类型名
  18. {
  19. 枚举元素表
  20. };
  • enum是关键字
  • 枚举类型名必须是合法的标识符
  • 枚举元素表由多个标识符组成,标识符之间用逗号分隔。这些标识符通常是枚举型数据的值的名字。为了与符号常量相区别,值名通常用小写字母命名。
  • 最后要用分号结尾 ```c 例: enum weekday {sun, mon, tue, wed, thu, fri, sat};

enum weekday today, nextday; //定义变量 也可以 enum weekday {sun, mon, tue, wed, thu, fri, sat} today, nextday;

  1. - todaynextday具有enum weekday类型,它们的取值只能是sun, mon, ......这7种可能,而不能是其他值。
  2. ```c
  3. today = sun;
  4. nextday = mon;
  5. if(today == sat)
  6. nextday = sun;
  7. 但是
  8. today = 100; //错误

C语言编译时对枚举元素实际上按整型常量处理(因此除定义外的程序中不可对其赋值)。

  1. today = sun;
  2. printf("%d", today);
  3. 输出结果
  4. 0

因此,也可以在枚举类型定义时指定枚举元素的值。

  1. enum weekday {sun = 7, mon = 1, tue, wed, thu, fri, sat};

此时,sun = 7, mon = 1,而tue及以后的值,依次从2开始递增(2,3,4……)
即 从最后一个指定值的项开始递增。