简述
概念
定义:
定义一个结构体类型的一般形式为:
struct 结构体名
{
数据类型 成员名1;
数据类型 成员名2;
:
数据类型 成员名n;
};
在大括号中的内容也称为“成员列表”或“域表”。
其中,每个成员名的命名规则与变量名相同;
数据类型可以是基本变量类型和数组类型,或者是一个结构体类型;
用分号“;”作为结束符。整个结构的定义也用分号作为结束符
例如:
#include
#include
struct student //在定义完结构体后可以直接省略名字
{
int num; //****
char name[10]; //**** **** **** 字节对其,补充空间
float grade; //****
}stu3 = {3,"wu",87.5};
int main(int argc, const char* argv[])
{
struct student stu1;
struct student stu2 = { 2,"li",90.5 };
stu1.num = 1;
//stu1.name = "zhangsan"; 错误用法
#if 0
stu1.name[0] = 'z';
stu1.name[1] = 'h';
stu1.name[2] = 'i';
stu1.name[3] = 's';
stu1.name[4] = 'a';
stu1.name[5] = 'n';
#endif
strcpy(stu1.name, "zhisan");
stu1.grade = 85.5;
printf("%d %s %f\n", stu1.num, stu1.name, stu1.grade);
printf("%d %s %f\n", stu2.num, stu2.name, stu2.grade);
printf("%d %s %f\n", stu3.num, stu3.name, stu3.grade);
printf("%d\n",sizeof(struct student));//查看结构体的大小
return 0;
}
先定义结构体类型再定义变量名(这是C语言中定义结构体类型变量最常见的方式)
struct 结构体名
{
成员列表;
};
struct 结构体名 变量名;
例如:定义几个职工变量:struct worker
{
long number;
char name[20];
char sex;
int age;
float salary;
char address[80];
char phone[20];
};
struct worker worker1,worker2;
注意事项:
“struct worker”代表类型名,不能分开写
struct worker1,worker2;
//错误,没有指明是哪种结构体类型
worker worker1,worker2;
//错误,没有struct关键字//系统不认为worker是结构体类型
为了使用上的方便,程序员通常用一个符号常量代表一个结构体类型。即在程序开头加上下列语句:
#define WORKER struct worker;
这样在程序中,WORKER与struct worker完全等效。
例如:
WORKER
{
long number;
char name[20];
char sex;
int age;
float salary;
char address[80];
char phone[20];
};
WORKER worker1,worker2;
此时,可以直接用WORKER定义worker1、worker2两个变量,而不必再写关键字struct。
在定义类型的同时定义变量
这种形式的定义的一般形式为:
struct 结构体名
{
成员列表;
}变量名;
例如:
struct worker
{ long number;
char name[20];
char sex;
int age;
float salary;
char address[80];
char phone[20];
} worker1,worker2;
直接定义结构类型变量:
其一般形式为:
struct //没有结构体名
{
成员列表;
}变量名;
例如:
struct
{
long number;
char name[20];
char sex;
int age;
float salary;
char address[80];
char phone[20];
} worker1,worker2;
一个结构体变量占用内存的实际大小,也可以利用sizeof求出。它的运算表达式为:
sizeof(运算量) //求出给定的运算量占用内存空间的字节数
其中运算量可以是变量、数组或结构体变量,可以是数据类型的名称。
例如:
sizeof(struct worker)
sizeof(worker1)
结构体变量是不同数据类型的若干数据的集合体。在程序中使用结构体变量时,一般情况下不能把它作为一个整体参加数据处理,而参加各种运算和操作的是结构体变量的各个成员项数据。
结构体变量的成员用以下一般形式表示:
结构体变量名.成员名
例如,上面给出的结构体变量worker1具有下列七个成员:
worker1.number;worker1.name;worker1.sex;worker1.phone;worker1.age;worker1.salary;worker1.address;
在定义了结构体变量后,就可以用不同的赋值方法对结构体变量的每个成员赋值。例如:
strcpy(worker1.name,”Zhang San”);
worker1.age=26;
strcpy(worker1.phone,”1234567”);
worker1.sex=’m’;
除此之外,还可以引用结构体变量成员的地址以及成员中的元素。例如:引用结构体变量成员的首地址&worker1.name;引用结构体变量成员的第二个字符worker1.name[1];引用结构体变量的首地址&worker1。
注意:
不能将一个结构体类型变量作为一个整体加以引用,而只能对结构体类型变量中的各个成员分别引用。
例如,对上面定义的结构体类型变量wan,下列引用都是错误的:
cout<>wan;
但是可以如下引用
cout<>wan.name;
如果成员本身又属一个结构体类型,则要用若干个成员运算符,一级一级地找到最低的一级成员。只能对最低级的成员进行赋值或存取以及运算。
例如,对上面定义的结构体类型变量worker1,可以这样访问各成员:
worker1.age
worker1.name
worker1.birthday.year
worker1.birthday.month
worker1.birthday.day
注意:不能用worker1.birthday来访问worker1变量中的成员birthday,因为birthday本身是一个结构体变量。
对成员变量可以像普通变量一样进行各种运算(根据其类型决定可以进行的运算)。例如:
worker2.age=worker1.age;
sum=worker1.age+worker2.age;
worker1.age++;
在数组中,数组是不能彼此赋值的,而结构体类型变量可以相互赋值。
与其他类型变量一样,也可以给结构体的每个成员赋初值,这称为结构体的初始化。一种是在定义结构体变量时进行初始化,语法格式如下:
struct 结构体名 变量名={初始数据表};
另一种是在定义结构体类型时进行结构体变量的初始化。
struct 结构体名
{
成员列表;
}变量名={初始数据表};
struct student wan={”Wan Jun”,’m’,20,” SuZhou Road No.100”};
等价于下列代码:
strcpy(wan.name,” Wan Jun”);
wan.sex = ’m’;
wan.age = 20;
strcpy(wan.addr, ” SuZhou Road No.100”);
具有相同结构体类型的结构体变量也可以组成数组,称它们为结构体数组。结构体数组的每一个数组元素都是结构体类型的数据,它们都分别包括各个成员(分量)项。
定义结构体数组的方法和定义结构体变量的方法相仿,只需说明其为数组即可。可以采用三种方法:
先定义结构体类型,再用它定义结构体数组。
结构体数组的定义形式如下:
struct 结构体名
{
成员表列;
};
struct 结构体名
例如:
struct student
{
char name[20];
char sex;
int age;
char addr[20];
};
struct student stu[3];
在定义结构体类型同时定义结构体数组。
结构体数组的定义形式如下:
struct 结构体名
{
成员表列;
}数组名[元素个数];
例如:
struct student
{
char name[20];
char sex;
int age;
char addr[20];
}stu[3];
直接定义结构体数组
结构体数组的定义形式如下:
struct //没有结构体名
{
成员表列;
}数组名[元素个数];
例如:
struct
{
char name[20];
char sex;
int age;
char addr[20];
}stu[3];
代码示例:
#include
#include
struct student{
int num;
char name[10];
float grade;
}s1[1] = {4 , "zhang", 80.5};//第三种
int main(int argc, const char *argv[])
{
struct student s[4] = {{1,"zhi",90.5},{2,"li",80.5},{3,"zhao",77.5}};//第二种
/* 第一种
struct student s[4];
s[0].num = 1;
#if 0
stu1.name[0] = 'Z' ;
stu1.name[1] = 'H' ;
stu1.name[2] = 'i' ;
#endif
strcpy(s[0].name, "ZHi");
s[0].grade = 90.5;
*/
printf("%d %s %f\n",s[0].num ,s[0].name ,s[0].grade);
printf("%d %s %f\n",s[1].num ,s[1].name ,s[1].grade);
printf("%d %s %f\n",s[2].num ,s[2].name ,s[2].grade);
printf("%d %s %f\n",s1[0].num ,s1[0].name ,s1[0].grade);
return 0;
}
结构体数组在定义的同时也可以进行初始化,并且与结构体变量的初始化规定相同,只能对全局的或静态存储类别的结构体数组初始化。
结构体数组初始化的一般形式是:
struct 结构体名
{
成员列表;
};
struct 结构体名 数组名[元素个数]={初始数据表};
或是
struct 结构体名
{
成员表列;
}数组名[元素个数]={初始数据表};
由于结构体变量是由若干不同类型的数据组成,而结构体数组又是由若干结构体变量组成。所以要特别注意包围在大括号中的初始数据的顺序,以及它们与各个成员项间的对应关系。
一个结构体数组的元素相当于一个结构体变量,因此前面介绍的有关结构体变量的规则也适应于结构体数组元素。以上面定义的结构体数组stu[3]
为例说明对结构体数组的引用:
引用某一元素中的成员。
stu[1].name
可以将一个结构体数组元素值赋给同一结构体类型的数组中的另一个元素,或赋给同一类型的变量。如:struct student stu[3],student1;
现在定义了一个结构体类型的数组,它有3个元素,又定义了一个结构体类型变量student1,则下面的赋值是合法的。
student1=stu[0];
stu[0]=stu[1];
stu[1]=student1;
不能把结构体数组元素作为一个整体直接进行输入输出。
如printf(“…”,stu[0]);
或scanf(“…”,&stu[0]);
都是错误的
只能以单个成员为对象进行输入输出,如:
scanf(“…”,stu[0].name);
scanf(“…”,&stu[1].num);
printf(“…”,stu[0].name);
printf(“…”,stu[1].num);
代码举例:
#include
#include
struct student{
int num;
char name[10];
float grade;
}s1[1] = {4 , "zhang", 80.5};//第三种
int main(int argc, const char *argv[])
{
struct student s[4] = {{1,"zhi",90.5},{2,"li",80.5},{3,"zhao",77.5}};//第二种
/* 第一种
struct student s[4];
s[0].num = 1;
#if 0
stu1.name[0] = 'Z' ;
stu1.name[1] = 'H' ;
stu1.name[2] = 'i' ;
#endif
strcpy(s[0].name, "ZHi");
s[0].grade = 90.5;
*/
printf("%d %s %f\n",s[0].num ,s[0].name ,s[0].grade);
printf("%d %s %f\n",s[1].num ,s[1].name ,s[1].grade);
printf("%d %s %f\n",s[2].num ,s[2].name ,s[2].grade);
printf("%d %s %f\n",s1[0].num ,s1[0].name ,s1[0].grade);
return 0;
}
可以设定一个指针变量用来指向一个结构体变量。此时该指针变量的值是结构体变量的起始地址,该指针称为结构体指针。
结构体指针与前面介绍的各种指针变量在特性和方法上是相同的。与前述相同,在程序中结构体指针也是通过访问目标运算“*
”访问它的对象。结构体指针在程序中的一般定义形式为:
struct 结构体名 *结构指针名
;
其中的结构体名必须是已经定义过的结构体类型。
例如,对于上面中定义的结构体类型struct student
,可以说明使用这种结构体类型的结构指针如下:
struct student *pstu;
其中pstu
是指向struct student
结构体类型的指针。结构体指针的说明规定了它的数据特性,并为结构体指针本身分配了一定的内存空间。但是指针的内容尚未确定,即它指向随机的对象。
当表示指针变量p所指向的结构体变量中的成员时,“(*结构体指针名).成员名
”这种表示形式总是需要使用圆括号,显得很不简炼。因此,对于结构体指针指向的结构体成员项,给出了另外一种简洁的表示方法,如下表示:
结构体指针名->成员名
它与前一种表示方法在意义上是完全等价的。
例如,结构体指针p指向的结构体变量中的成员name可以表示如下:
(*p).name 或 p->name
代码举例:
#include
#include
struct student{
int num;
char name[10];
float grade;
};
int main(int argc, const char *argv[])
{
struct student *p;
struct student stu1 = {1,"zhao",98};
p = &stu1;
/* 可能会出现内存分配的问题
p->num = 1;
strcpy(p->name , "zhao");
p->grade = 90.5;
*/
printf("%d %s %f\n",stu1.num ,stu1.name ,stu1.grade);
printf("%d %s %f\n",(*p).num ,(*p).name ,(*p).grade);//一种方式
printf("%d %s %f\n",p->num ,p->name ,p->grade);//常用的一种方式
return 0;
}