C语言基础学习---结构、联合、枚举

15. 结构、联合、枚举

结构是具有不同类型的值得集合,联合和结构类似,不同之处在于联合的成员共享同一存储空间,这样的结果是,联合可以每次存储一个成员,但是无法同时存储全部成员。枚举是一种证书类型,值由程序员来命名。

结构有点像Java中类的概念。

15.1 结构变量

15.1.1 结构变量声明

1
2
3
4
5
struct{
int number;
char name [25 + 1];
int on_hand;
}part1,part2;

struct{}指明了类型,part1 part2 是具有这种类型的变量。

结构的成员在内存中是按照声明的顺序存储的。

15.1.2 结构变量初始化

1
2
3
4
5
6
7
8
9
10
struct{
int number;
char name [25 + 1];
int on_hand;
}part1 = {31231,"Disk driver",10},
part2 = {4323,"Printer cable",34};


//或者指定初始化
{.number=23423, .name = "xxx", .on_hand = 333;}

15.1.3 对结构的操作

1
printf("Part numer is: %d",part.number);

类似于 Java 操作类的成员变量的方式。

但是C语言没有提供其他用于整个结构的操作,特别是不能够使用运算符 == != 来判定两个结构是相等的还是不等。

15.2 结构类型

1
2
3
4
5
6
7
8
9
10
11
12
struct{
int number;
char name [25 + 1];
int on_hand;
}part1;


struct{
int number;
char name [25 + 1];
int on_hand;
}part2;

Part1 和 part2 不具有兼容的类型,因此不可以吧 part1 给 part2。

解决方法:声明「结构标记」,或者使用「typedef」来定义类型名

15.2.1 结构标记的声明

1
2
3
4
5
6
7
8
9
10
struct part{
int number;
char name [25 + 1];
int on_hand;
}; //这里分号不能省略
//part 就是结构标记,可以用它声明变量

struct part part1,part2;

//有点像Java当中类的定义和实例化

15.2.2 结构类型的定义

1
2
3
4
5
6
7
typedef struct{
int number;
char name [25 + 1];
int on_hand;
} Part;//这里定义的就是Part类型
//可以向使用内置类型一样使用Part
Part part1,part2;

15.2.3 结构数组初始化

1
2
3
4
5
6
7
8
9
10
11
12
struct dialing_code{
char *contruy;
int code;
};

//初始化方式1
const struct dialing_code country_codes[] = {
{"aaa",1}, {"bb",2}, {"vvv",3}, {"eee",4}, {"www",5},
{"dfd",356}, {"vds",24}, {"efs",76}, {"qwe",234}, {"fe",3}
}
//初始化方式2 C99
struct part inventory[100] = {[0].number = 1,[0].on_hand = 122, [0].name = "dwqq"};

15.2 联合

联合也是有一个或者多个成员构成,这些成员可以有不同的类型,但是编译器只为联合中最大的成员分配足够的内存空间,联合的成员在这个空间内彼此覆盖。

1
2
3
4
5
6
7
8
union{
int i;
double d;
}u;
struct{
int i;
double d;
}s;

结构变量 s 和联合变量 u 在内存中情况如下:

联合的性质和结构性质几乎一致。在初始化联合的时候,只有联合的第一个成员可以获得初始值。

1
2
3
4
union{
int i;
double d;
}u={0};

C99可以指定和结构一样指定初始化,指定初始化允许我们指定需要对联合中的哪个成员进行初始化,但是不一定是第一个。

1
2
3
4
union{
int i;
double d;
}u={.d = 10.0};

15.2.1 用联合节省空间

统计礼品册售出的商品信息,有三种商品

  • 书籍:书名,作者,页数
  • 杯子:设计
  • 衬衫:设计、可选颜色、可选尺寸
1
2
3
4
5
6
7
8
9
10
11
struct catalog_item{
int stock_number;
float price;
int item_type;
char title[TITLE_LEN + 1];
char author[AUTHOR_LEN + 1];
int num_pages;
char desigon[DESIGN_LEN + 1];
int colors;
int sizes;
}

成员 item_type 是 BOOK MUG SHIRT 之一。但是这样会浪费大量的空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct catalog_item{
int sock_number;
float price;
int item_type;
union{

struct{
char title[TITLE_LEN + 1];
char author[AUTHOR_LEN + 1];
int num_pages;
}book;

struct{
char desigon[DESIGN_LEN + 1];
}mug;

struct{
char desigon[DESIGN_LEN + 1];
int colors;
int sizes;
}shirt;

}item; //联合 item 是结构 catalog_item 的成员。
};

根据联合的性质, catalog_item 这个结构就不会浪费空间。

联合的两个或多个成员是结构,二这些结构最初的一个或者多个成员是相匹配的「成员顺序应该相同吗,类型也箭筒,名字可以不一样」,如果当前某个结构有效,则其他结构中的匹配成员也有效。

15.2.2 用联合来构造混合数据结构的数组

假设需要一个数组既可以存储int类型,也可以存储doubel类型,可以这么写:

1
2
3
4
5
6
7
8
typedef unio{
int i;
double d;
}Number;

Number number_array[1000];
number_array[0].i = 5;
number_array[1].d = 8.545;

但是这种方式没办法确定,一个 Number 中经过多次修改之后,最后包含的到底是 int 还是 double。解决方法:将联合嵌入一个结构中,结构中还有另外一个标记成员变量。

1
2
3
4
5
6
7
8
9
10
11
typedef struct {
int kind;
unio{
int i;
double d;
}u;
} Number;

n.kind = INT_KIND;
n.u.i = 82;
//这么一来,通过 kind 标记量就可以分辨出当前 u 联合中存储的是什么类型的变量了

15.3 枚举

  • 命名枚举两种方法:通过声明标记的方法,或者使用 typedef 来创建第一无二的类型名。
  • 默认情况下,编译器会把整数0,1,2,3,赋给特定枚举类型中的常量;可以为枚举常量自由选择不同的值;两个或者多个枚举常量具有相同的值也是合法的;当没有为枚举常量指定值时,它的值比前一个常量的值大1,第一个枚举常量的默认值为0.
1
2
3
4
5
6
7
8
enum suit{CLUBS,DIAMONDS,HEARTS,SPADES};
enum suit s1, s2;

typedef enum {CLUBS,DIAMONDS,HEARTS,SPADES} Suit;
Suit s1,s2

//CLUBS =0, HEARTS = 79
enum suit{CLUBS,DIAMONDS=78,HEARTS,SPADES=34};
共字
0%
.gt-container a{border-bottom: none;}