十、结构体和共用体
10.1 概述
在实际问题中,一组数据往往具有不同的数据类型。当然不能用一个数组来存放这种数据。因为数组中各元素的类型和长度都必须一致,以便于编译系统处理。
C语言中给出了另一种构造数据类型——“结构(structure)“或叫"结构体”。"结构体”是一种构造类型,它是由若干"成员"组成的。每一个成员可以是一个基本数据类型或者又是一个构造类型。
10.2 定义结构体
struct 结构体名
{
成员表列;
};
例如,
struct stu
{
int num;
char name[20];
char sex;
float score;
};
10.2.1 结构体变量的声明
(1)先定义结构体,再声明结构体变量。
struct stu
{
int num;
char name[20];
char sex;
float score;
};
struct stu boy1, boy2; //声明了两个变量boy1和boy2为stu结构类型。
或使用宏定义使一个符号常量来表示一个结构体类型。
#define STU struct stu
STU
{
int num;
char name[20];
char sex;
float score;
};
STU boy1, boy2; //声明了两个变量boy1和boy2为stu结构类型。
(2)在定义结构体类型的同时说明结构体变量。
struct 结构名
{
成员表列;
}变量名表列;
如,
struct stu
{
int num;
char name[20];
char sex;
float score;
}boy1, boy2;
(3)直接说明结构体变量
struct
{
成员表列;
}变量名表列;
如,
struct
{
int num;
char name[20];
char sex;
float score;
}boy1, boy2;
10.2.2 结构体变量成员的表示方法
在程序中使用结构体变量时,往往不把它作为一个整体来使用。一般对结构体变量的使用,包括赋值、输入、输出、运算等都是通过结构体变量的成员来实现的。
结构体变量成员的一般形式为:结构体变量名.成员名
(1)结构体变量的赋值:
boy1.num = 32;
boy1.name = "大白";
(2)结构体变量的初始化:结构体的初始化与数组的初始化类似——只要将元素列在一对大括号中,每个元素之间用逗号隔开。
struct stu boy1 = {32, "大白", "女", 12.5};
struct stu boy1 = {.num=32, .score=12.5} //允许以任意顺序对成员进行初始化,也可以仅初始化指定成员。
boy2 = boy1;
复合字面量:在单个语句中为一个结构体指定一个或多个值。
struct date
{
int year;
int month;
int day;
};
today = (struct date) {2022, 12, 1};
或
today = (struct date) {.month=12, .year=2015, .day=1};
10.3 结构体数组
数组的元素也可以是结构体类型的,因此可以构成结构体型数组。结构体数组的每一个元素都是具有相同结构体类型的下标结构体变量。
struct date Date[5]; //定义了一个结构体数组,共 5 个元素
10.4 结构体指针变量
10.4.1 指向结构体变量的指针:
一个指针变量当用来指向一个结构体变量时,称之为结构体指针变量。结构体指针变量中的值是所指向的结构体变量的首地址。通过结构体指针即可访问该结构体变量。
结构体指针变量声明的一般形式为:struct 结构体名 *结构体指针变量
结构体变量的成员访问:
结构体变量.成员名
(*结构体指针变量).成员名
结构体指针变量->成员名
struct date *pdate; //定义一个指向 date 的指针变量 pdate
pdate = &today; //赋值是把结构变量的首地址赋予该指针变量;
不能把结构名赋予该指针变量:
pdate = &date; //错误
访问结构体变量的成员:
today.year;
(*pdate).year; // 因为成员符”.”的优先级高于“*",所以不能去掉括号。
pdate->year;
10.4.2 指向结构体数组的指针:
指针变量可以指向一个结构体数组,这时结构体指针变量的值是整个结构数组的首地址。结构体指针变量也可指向结构数组的一个元素,这时结构体指针变量的值是该结构体数组元素的首地址。
struct date Date[3] = {
{2011, 11, 2},
{2012, 12, 13},
{2022, 10, 11}
};
struct date *pdate;
pdate = Date;
pdate = &Date[0];
pdate 为指向结构体数组的指针变量,则 pdate 也指向该结构体数组的 0 号元素,pdate+1指向1号元素,pdate+i 则指向 i 号元素。这与普通数组的情况是一致的。
注意:
一个结构体指针变量虽然可以用来访问结构体变量或结构体数组元素的成员,但是,结构体指针变量不能指向一个成员。也就是说不允许取一个成员的地址来赋予它。
错误:
pdate = &Date[1].year; //错误的
10.4.3 结构体指针变量作函数参数:
虽然允许用结构变量作函数参数进行整体传送。但是这种传送要将全部成员逐个传送,特别是成员为数组时将会使传送的时间和空间开销很大,严重地降低了程序的效率。
因此最好的办法就是使用指针,即用指针变量作函数参数进行传送。这时由实参传向形参的只是地址,从而减少了时间和空间的开销。采用指针变量作运算和处理,故速度更快,程序效率更高。
//定义求平均日期的函数;
struct date Date[3] = {
{2011, 11, 2},
{2012, 12, 13},
{2022, 10, 11}
};
void avg(struct date *pdate);
int main()
{
struct date *pdate;
void avg(struct date *pdate);
pdate = Date;
avg(pdate);
}