用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体
例如,一个学生的学号、姓名、性别、年龄、成绩、家庭地址等项,是属于同一个学生的,因此组成一个组合数据,如student_1的变量,反映它们之间的内在联系
struct Student
{
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
};
- 定义结构体类型变量
(1) 结构体类型与结构体变量是不同的概念,不要混同。只能对变量赋值、存取或运算,而不能对一个类型赋值、
存取或运算。在编译时,对类型是不分配空间的,只对变量分配空间。
(2) 结构体类型中的成员名可以与程序中的变量名相同,但二者不代表同一对象。
(3) 对结构体变量中的成员(即“域”),可以单独使用,它的作用与地位相当于普通变量。
(4)结构体变量中的成员访问,采用 .运算符访问
- 结构体内存分配
- 结构体变量的初始化和引用
说明:
(1)定义结构体数组一般形式是
① struct 结构体名
{成员表列} 数组名[数组长度];
② 先声明一个结构体类型,然后再用此类型定义结构体数组:
结构体类型 数组名[数组长度];
如:struct Person leader[3];
(2)对结构体数组初始化的形式是在定义数组的后面加上:
={初值表列};
如: struct Person leader[3]= {"Li",0,"Zhang",0,"Fun",0};
- 指向结构体变量的指针
指向结构体对象的指针变量既可以指向结构体变量,也可以用来指向结构体数组中的元素。
指针变量的基类型必须与结构体变量的类型相同。例如:
struct Student *p;
为了使用方便和直观,通常使用结构体指针访问成员使用->运算符,而不使用(*结构体指针变
量).这种形式去访问成员变量。
改成->运算符访问成员变量
p->num = 10101;
strcpy(p->name,”Zhang”);
p->score = 92.5;
- 用结构体变量和结构体变量的指针作函数参数
将一个结构体变量的值传递给另一个函数,有3个方法。
(1) 用结构体变量的成员作参数。
例如,用stu[1].num或stu[2].name作函数实参,将实参值传给形参。
- 用法和用普通变量作实参是一样的,属于“值传递”方式。
- 应当注意实参与形参的类型保持一致。
例如: funA(stu[1].num);
(2) 用结构体变量作实参。
- 用结构体变量作实参时,将结构体变量所占的内存单元的内容全部按顺序传递给形参,形参也必须是同类型的结构体变量
- 在函数调用期间形参也要占用内存单元。这种传递方式在空间和时间上开销较大
- 在被调用函数期间改变形参(也是结构体变量)的值,不能返回主调函数
- 一般较少用这种方法
例如: funB(stu[1]);
(3)用指向结构体变量(或数组元素)的指针作实参,将结构体变量(或数组元素)的地址传给形参。
例如: funC(&stu[1]);
结构体内包含另一个结构体
struct A { struct B {
char c; struct A a;
int *i; float f;
}; };
结构体内包含函数指针
struct TEST {
float f;
void (*func)(void);
}
- 结构体位域
struct 位域结构体名 { 位域列表};
位域列表为: 类型说明符 位域名:长度;
struct BitField {
unsigned char a : 2; // 第一个位域,2位
unsigned char b : 4; // 第二个,4位
unsigned char c : 2; // 第三个,2位
}Field;
位域可以没有名字的,这时它只用来作填充或调整位置。无名的位域是不能使用的struct BitFiled_1
{
unsigned a : 4;
unsigned : 0; // 无名位域, 无法使用 unsigned b : 4;
unsigned c : 4;
} Filed_1 ;
宽度为 0 的一个未命名位域强制下一位域对齐到其下一type位域的边界struct BitFiled_1 {
unsigned a : 4; //第1个unsigned int
unsigned : 0; // 未命名位域
unsigned b : 4; // 从第二个unsigned int
unsigned c : 4; // 还是第二个unsigned int
} Filed_1; // 该位域结构总共 8 Byte