1.概述
C语言允许用户自己指定这样一种数据结构,它由不同类型的数据组合成一个整体,以便使用,这些组合在一个整体中的数据是互相关联的,这样的数据结构称为结构 体,它相当于高级语言中记录。
声明一个结构体类型一般形式如下:
struct 结构体名
{成员列表}; //此处为“ ;” (分号)不是 “, ‘(逗号);
如:
struct student
{
char name[5];
char id[10];
int scores;
}; //此处的分号不能漏掉,否则报错。
结构体名,用作结构类型的标志,它又称结构标记,大括号内是该结构体的各个成员,由它们组成一个结构体,对各成员都进行类型声明;
这里的student就是结构体名,不同的结构体名表示不同的结构体类型,如student stu{成员变量};和student stu1{成员变量};就是不同的结构体类型;
2.定义结构体类型变量的方法
前边只是定义了一个结构体类型,它相当于一个模型,但其中并无具体数据,系统对之也不分配实际的内存单元为了能在程序中使用结构体类型数据,应当定义结构体类型的变量,并在其中存放具体的数据,可以采取以下3中方法定义结构体类型变量。
(1)先定义结构体类型再定义变量名
如上面已经定义了一个结构体类型 struct student ,可以用它来定义变量。如:
struct student stu1; //此处的struct student要一起使用,它们整体才能够标志结构体类型,否则报错。
在定义了结构体变量后,系统会位置分配内存单元。例如stu1在内存中占20个字节,关于结构体变量如何在内存中申请内存请参照本博客的“C语言结构体(一)”。
(2)定义结构体类型时,一起定义结构体类型变量;
struct 结构体名
{
成员表列;
}变量名表列;
(3)直接定义结构体类型变量
struct //与(2)的区别是此处省略了结构体名;
{
成员表列;
} 变量名列表;
关于结构体类型,有几点要说明:
a.类型与变量时不同的概念,不是混同,只能对变量赋值,存取或运算,而不能对一个类型赋值,存取或运算。在编译时,对类型是不分配空间的,只对变量分配空间。
b.对结构体中的成员可以单元使用,它的作用相当于普通变量。
c.成员也可以是一个结构体变量。
如:
struct data
{
int month;
int day;
int year;
};
struct student
{
char name[5];
char id[10];
strcut data birthday;
int scores;
}stu1;
d.成员名可以与程序中的变量名和结构体名相同,它们之间互不影响。
3.结构体变量的引用
(1)不能将一个结构体变量作为一个整体进行输入和输出。
只能对结构体变量中的各个成员分别进行输入输出。应用结构体变量中的成员的方式为
结构体变量名.成员名
例如stu1.name表示stu1变量中的name成员
"."成员(分量)运算符,它在所有的运算符中优先级最高,因此可以把stu1.name作为一个整体来看待。
(2)如果成员本身又属一个结构体类型,则要用若干个成员运算符,一级一级的找到最低一级的成员。只能对最低的成员进行赋值或存取以及运算。
(3)对结构体变量的成员可以像普通变量一样进行各种运算(根据其类型决定可以进行的运算)。
++stu1.socres;
由于"."运算符的优先级最高,因此stu1.age++是对stu1.scores 进行自加运算。而不是先对scores进行自加运算。
(4)可以引用结构体变量成员的地址。也可以引用结构体变量的地址。
结构体变量的地址主要用于作函数参数,传递结构体地址。
4.结构体变量的初始化
和其它类型变量一样,对结构体变量可以在定义时指定初始值。
如:
struct student
{
char name[5];
char[id];
int scores;
}stu1={"sun","20121214",90};
5.结构体数组
一个结构体变量中可以存放一组数据(如一个学生的姓名,学号,成绩等数据)。如果有10个学生的数据需要参加运算,显然应该用数组,这就是结构体数组。结构体数组和数值型数组不同之处在于每个数组元素都是一个结构体类型的数据,它们分别包括各个成员。
6.指向结构体类型数据的指针
一个结构体变量的指针就是该变量所占据的内存段的起始地址,可以设一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始位置。指针变量也可以用来指向结构体数组中的元素。
6.1指向结构体变量的指针
指向结构体变量的指针的应用:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
struct student
{
char id[10];
char name[5];
int scores;
};
void main()
{
struct student stu1;
struct student *p;
p=&stu1;
strcpy(stu1.name,"Sun");
strcpy(stu1.id,"2012121404");
stu1.scores=90;
printf("ID:%s name:%s socres:%f",stu1.id,stu1.name,stu1.socres);
printf("ID:%s name:%s socres:%f" p->id,p->stu1.name,p->socres);
printf("ID:%s name:%s socres:%f"(*p).id,(*p).name,(*p).socres);
system("pause");
}
可以看到三个printf输出的结果相同。
在C语言中,为了方便和使之直观,可以把(*p).scores改用p->scores来代替,它表示*p所指向的结构体变量中的scores成员,同样(*p).scores等价于p->scores。
也就是说一下三种形式等价:
a.结构体变量.成员名
b.(*p).成员名
c.p->成员名
其中->成为指向运算符
6.2 指向结构体数组的指针
既然可以使用指向数组或数组元素的指针和指针变量,同样对结构体数组及其元素 也可以用指针变量来指向。
#include <stdio.h>
#include <stdlib.h>
struct student
{
char id[10];
char name[5];
int scores;
};
struct student stu[3]={{"1111","sun",18},{"2222","tian",19},{"3333","sheng",20}};
int main()
{
struct student *p;
printf("No---------------Name--------------scores\n");
for(p=stu;p<stu+3;p++)
//-表示左对齐
printf("%s %-5s %d\n",p->id,p->name,p->scores);
system("pause");
return 0;
}