定义和使用结构体变量
自己建立结构体类型
由不同数据组成的组合型的数据类型,它称为结构体(structre)
声明一个结构体类型的一般形式为
struct 结构体名
{
成员表列};
结构体类型的名字是由一个关键字struct和结构体名组合而成的(例如 struct Student)。结构体名是由用户指定的,又称“结构体标记”,以区别于其他结构体类型。
花括号内是该结构体所包含的的子项,称为结构体的成员(member),
对各成员进行类型声明
类型名 成员名;
成员表列也称为域表,每一个成员是结构体中的一个域,成员命名规则与变量名相同
结构体并非只有一种,而是可以设计出许多中结构体类型
成员可以属于另一个结构体类型
//例如:
struct Date //声明一个结构体类型struct Date
{
int month; //月
int day; //日
int year; //年
}
struct Student //声明一个结构体类型struct Student
{
int num;
char name[20];
char sex;
int age;
struct Data birthday; //成员birthday属于struct Date类型
char addr[30];
}
定义结构体类型变量
先声明结构体类型,再定义该类型的变量
例如:
struct Student student1,student2;//定义了student1,student2为struct Student类型的变量,student1和student2具有struct Student类型的结构
在定义了结构体变量后,系统会为之分配内存单元。根据结构体类型中包含的成员情况,在Visual C++中占63个字节(4+20+1+4+4+30=63)
计算机对内存的管理是以“字”为单位的(许多计算机系统以4个字节为一个“字”)。如果在一个“字”中只存放了一个字符,虽然只占一个字节,但该“字”中的其他3个字节不会接着存放下一个数据,而会从下一个“字”开始存放其他数据,因此在用sizeof运算符测试struct1的长度时,得到的不是理论值63,必然是4的倍数
在声明类型的同时定义变量
例如:
struct Student
{
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}student1,student2;
它的作用和第一种方法相同,但是在定义struct Student类型的同时定义两个struct Student类型的变量student1,student2。
这种定义方法的一般形式为
struct 结构体名
{
成员表列
}变量名表列;
声明类型和定义放在一起进行,能直接看到结构体的结构,比较直观,在写小程序时用此方式比较方便,但写大程序时,往往要求对整型的声明和变量的定义分别放在不同的地方,以便程序结构清晰,便于维护,所以一般不多用这种方式
不指定类型名而直接定义结构体类型变量
其一般形式为
struct
{
成员表列
}变量名表列;
指定了一个无名的结构体类型,它没有名字(不出现结构体名)。虽然不能再以此结构体类型去定义其他变量,这种方式用得不多
- 说明:
结构体类型和结构体变量是不同的概念。只能对变量赋值、存放或预算,而不能对一个类型赋值、存取或与运算。在编译时,对类型是不分配空间的,只对变量分配空间- 结构体类型中的成员可以与程序中的变量名相同,但二者不代表同一对象。例如,程序中可以另定义一个变量num,它与struct Student中的num是两回事,互不干扰
- 对结构体变量中的成员(即“域”)可以单独使用,它的作用与地位相当于普通变量
结构体变量的初始化和引用
在定义结构体变量时,可以对它初始化,即赋初始值,然后可以引用这个变量
//例如:
//把一个学生的信息(包括学号、名字、性别、地址)放在同一个结构体变量中,然后输出这个学生的信息
#include<stdio.h>
int main()
{
struct Student //声明结构体类型struct Student
{
long int num; //以下四行为结构体的成员
char name[20];
char sex;
char addr[20]; //定义结构体变量a并初始化
}a = {
10101,"Li Lin",'M',"123 beijing Road" };
printf("NO.:%ld\nname:%s\nsex;%c\naddress:%s\n", a.num, a.name, a.sex, a.addr);
return 0;
}
运行结果:
NO.:10101
name:Li Lin
sex;M
address:123 beijing Road
在定义结构体变量时可以对它的成员初始化。初始化列表是用花括号括起来的一些常量,这些常量依次赋给结构体变量中的各成员
可以引用结构体变量中的成员的值,引用方式为
结构体变量名.成员名
sudent.num=10010;//"."是成员运算符,它在所有运算符中优先级最高
如果成员本身又属于一个结构体类型,则要用若干个成员运算符,一级一级地找到最低的一级的成员,只能对最低级的成员进行赋值或存取以及运算
引用方式:
student.num //结构体变量student1中的成员num
student.birthday.mother //结构体变量student1中的成员的birthday中的的成员的month
对结构体变量的成员名可以像普通变量一样进行各种运算(根据其类型决定可以进行的运算)
student2.score=studen1.score; //赋值运算
sum=student1.score+student2.score; //加法运算
student.age++; //自加运算
同类的结构体变量可以互相赋值
student1=student2; //假设student1和student2已定义为同类型的结构体变量
可以引用结构体变量成员的地址,也可以引用结构体变量的地址
scanf("%d",&student1,num); //输入&student1.num的值
printf("%o",&student1); //输出结构体变量&student1的首地址
说明:结构体变量的地址主要用作函数参数,传递结构体变量的地址
使用结构体数组
定义结构体数组
定义结构体数的一般形式是
struct 结构体名
{
成员表列} 数组名[数组长度];
//先声明一个结构体类型,然后再用此类型定义结构体数组:
struct Person leader[3]; //leader是结构体数组名
对结构体数组初始化的形式是定义数组的后面加上:
={初值表列};
struct Person leader[3]={
"Li",0,"Zhang",0,"Sun",0};
结构体指针
所谓结构体指针就是指向结构体变量的指针,一个结构指针变量的起始地址就是这个结构体变量的指针。如果把一个结构体变量的起始位置存放在一个指针变量中,那么,这个指针变量就指向该结构体变量
指向结构体变量的指针
指向结构体对象的指针变量既可以指向结构体变量,也可指向结构体数组中的元素,指针变量的基类型必须与结构体变量的类型相同
struct Student *pt; //pt可以指向struct Student类型的变量或数组元素
//例如:
#include<stdio.h>
#include<string.h>
int main()
{
struct Student
{
long num;
char name[20];
char sex;
float score;
};
struct Student stu_1; //定义struct Student 类型的变量stu_1
struct Student* p; //定义指向struct Student类型数据的指针变量p
p = &stu_1; //p指向stu_1
stu_1.num = 10101; //对结构体变量的成员赋值
strcpy(stu_1.name, "li lin"); //用字符串复制函数给stu_1.name赋值
stu_1.sex = 'M';
stu_1.score = 89.5;
printf("No.%ld\nname:%s\nsex:%c\nscore:%5.1f\n", stu_1.num, stu_1.name, stu_1.sex, stu_1.score);
printf("No.%d\nnmae:%s\nsex:%c\nscore:%5.1f\n", (*p).num, (*p).name, (*p).sex, (*p).score);
return 0;
}
运行结果:
No.10101
name:li lin
sex:M
score: 89.5
No.10101
nmae:li lin
sex:M
score: 89.5
(*p).name等价于p->name。->称为指针运算符
如果p指向一个结构变量stu,以下3种用法等价
stu.成员名(如stu.num);
(*p).成员名(如(*p).num);
p->成员名(如p->num);
指向结构体数组的指针
可以用指针变量指向结构体数组的元素
#include<stdio.h>
struct Student//声明结构体类型struct Student
{
int num;
char name[20];
char sex;
int age;
};
struct Student stu[3] = {
{
10101,"li lin",'M',18}, {
10102,"zhang fang",'M',19},{
10104,"wang min",'F',20} };//定义结构体数组并初始化
int main()
{
struct Student* p;//定义指向struct Student结构体变量的指针变量
printf("No. Name sex age\n");
for (p = stu; p < stu + 3; p++)
printf("%5d %-20s %2c %4d\n", p->num, p->name, p->sex, p->age);//输出结果
return 0;
}
//(++p)-> 先使p自加1,然后得到p指向的元素中的num成员值(即10102)
//(p++)-> 先求得->num的值(即10101),然后再使p自加1,指向stu[1]
运行结果:
No. Name sex age
10101 li lin M 18
10102 zhang fang M 19
10104 wang min F 20
用结构体变量和结构体变量的指针作函数参数
将一个结构体变量的值传递给另一个函数,有三种方法:
- 用结构体变量的成员作参数(例如:用stu[1].num或stu[2].name作函数实参)应当注意实参和形参的类型保持一致
- 用结构体变量作实参。用结构体变量作实参时,采取的是值传递的方式,将结构体变量所占的内存单元的内存全部按顺序传递给形参,形参也必须是同类型的结构体变量
- 用指向结构体变量(或数组元素)的指针作实参,将结构体变量(或数组元素)的地址传给形参