设计程序最重要的一个步骤就是选择一个表示数据的好方法。使用简单的变量和数组时远远不够的,C使用结构变量(structure variable)进一步增强了表示数据的能力。接下来将介绍c语言中的数据类型结构体,联合以及枚举。
结构
结构体的声明
先看下面一个例子:
1 |
|
以上声明描述了一个有两个字符数组和float变量组成的结构。struct是关键词, 后面跟的是一个可选标记(单词book),最后以分号结尾。描述完结构,就可以以此结构模板声明变量,如:”struct book library;” 声明了一个以book结构设计的变量–libraty。
简略的声明方法:
1 |
|
结构体的初始化
结构体的一般初始化的方法
1 | struct book library { |
(C99)运用点(.)运算符初始化,点运算符可以用来访问结构体成员
只初始化成员value
1 | struct book test{ .vlaue = 10.99}; |
任意顺序指定初始化
1 | struct book temp{ |
结构数组
声明一个结构数组与其他类型数组类似
1 | struct book library[100]; |
访问数组元素的成员
1 | library[0].value /* 第1个数组元素的value成员*/ |
嵌套结构
在一个结构体嵌套另一个结构体
1 | struct names { //第一个结构 |
访问嵌套结构中的成员
1 | printf("Hello! %s\n", fellow.handle.first); |
指向结构的指针
声明和初始化
1 | struct guy fellow[2] = { // 声明包含2个元素的结构数组 |
这里值得注意一下,与数组不同,一个结构体的名字不是该结构体的地址,需要用&取址运算符。
用指针访问成员
1 | him = &fellow[0]; // him指向fellow[0] |
函数与结构体
直接通过代码理解
1 | /* book.c -- 仅包含一本书的图书目录 */ |
结构体的特性
数组与数组之间不能相互赋值,但是结构体可以
C允许把一个结构体赋值给另一个结构体
以上代码为例
1 | struct book library; |
得出的结果
1 | library address :0061FED0 |
二者存储的位置不同,属于深拷贝。
联合
联合(union)是一个能在同一个存储空间里(但不同时)存储不同类型的数据的数据类型。在结构中,各成员都占有自己的内存空间,它们是同时存在的。一个结构变量的总长度等于所有成员长度之和。在联合中,所有成员不能同时占用它的内存空间,它们不能同时存在。联合变量的长度等于最长的成员的长度。
结构变量可以作为函数参数,函数也可返回指向结构的指针变量。而联合变量不能作为函数参数,函数也不能返回指向联合的指针变量。但可以使用指向联合变量的指针,也可使用联合数组。
带标记的联合模板
1 | union hold { |
声明变量3个hold变量
1 | union hold fit; /* hold类型的联合变量*/ |
初始化变量
1 | union hold valA; |
下面是如何让使用联合(.)或(->):
1 | fit.digit = 23; /* 把23存储在fit, 使用2个字节 */ |
枚举
枚举类型(enumerated type)可以声明代表整数常量的符号名称。通过使用enum,可以创建一个新“类型”并指定它可以具有的值(实际上,enum常量是int类型)。枚举的目的是为了提高程序的可读性,它的语法与结构类似。
声明
以下是枚举变量的声明:
1 | enum 枚举名 {枚举元素1,枚举元素2,……}; |
如:
1 | enum spectrum {red, orange, yellow, green, violet, blue}; |
spectrum为标记名,color是一个变量,花括号里的内容red,orange… 实际都是int类型的常量{0, 1, 2,…}, 默认值时,它会被指定为0, 1, 2等常量
指定值时,
1 | enum levels {low = 10, medium = 500, high = 1000}; |
如果只对一个常量赋值,而后面为赋值时,
1 | enum feline {cat, lynx = 10, puma, tiger} |
那么cat为0, 而lynx, puma, tiger 为10,11,12。
示例
1 |
|
typedef
typedef是在计算机编程语言中用来为复杂的声明定义简单的别名,它与宏定义有些差异。它本身是一种存储类的关键字,与auto、extern、mutable、static、register等关键字不能出现在同一个表达式中。它与define相似,但它们有3个不同:
- 与define不同,typedef给出的符号名称仅限于对类型,而不是对值。
- typedef的解释由编译器,而不是预处理器执行。
- 虽然它的范围有限,但在其受限范围内,typedef比#define更灵活。
以下示例将展示它的用法:
定义变量类型:
1 | typedef unsigned char BYTE; /* BYTE是unsigned char 类型 */ |
这里BYTE大小写均可,大写可以方便区分。
指针的应用
1 | typedef char * STRING; |
STRING name相当于 char * name;
结构体中的应用
1 | typedef struct node{ |
这里注意node不是类型,必须配合struct一起使用;它只是一个临时标签可有可无。