一、为什么用结构体
C语言中的基本数据类型,用来描述现实生活中的一些事物,比如:一个学生有年龄、学号等属性,我们分别用 int 变量存储年龄、学号,那么我们会写出以下代码:
int age;
int num;
如果 我们想存储多个学生的信息那么有以下两种写法:
A 定义多个变量:
int age1,age2,age3;
int num1,num2,num3;
B 定义数组:
int age[10];
int num[10];
但是注意:年龄和学号之间是有联系的,他们都是某个学生的属性,以上代码在他们之间的联系上体现的不足:
比如 age1 与 num1 表示的是同一个学生还是 age1与num2表示的是同一个学生?
我们需要的是把学生看做一个整体在代码里表示,而不是把他的属性分散来看,C语言里用结构体这种组合类型来解决这个问题,关键字struct 。
二、结构体基本定义及使用
2.1 结构体定义
struct 结构体名{
类型 成员名;
类型 成员名;
.......
};
如果要创建一种类型要描述学生的信息,如编号,年龄,姓名,可以如下定义:
struct stu{
int num;//成员
int age;//成员
char name[10];//成员
};
2.2 结构体变量定义
struct stu 是数据类型(注意不是stu),c语言里定义变量的基本模型是:
数据类型 变量名;
int a;
所以定义 一个学生变量用如下方法:
struct stu stu1;
struct stu stu2,stu3;
stu1,stu2,stu3 是变量,变量的定义伴随这内存的分配,这时候会在内存中申请 sizeof(struct stu)个字节用来存储信息。
也可以在定义结构体的时候直接定义变量:(一般不这么使用)
struct stu{
int num;
int age;
char name[10];
}stu1,stu2;
注意这里每次定义变量的时候都要写struct 关键字,比较麻烦,我们可以使用typedef 来为struct stu起一个别名
typedef 简单回顾:
typedef 为已知类型起一个别名
比如
typedef int myint;
这里 myint a;等效于 int a;
typedef unsigned int uint;
这里 uint a;等效 unsigned int a;
对结构体typedef
typedef struct stu s_stu;
typedef struct stu* p_stu;
s_stu stu1;//等效于struct stu stu1;
p_stu p1;//等效于struct stu *p1;
也可以在定义结构体的时候直接typedef
typedef struct stu{
int age;
int num;
char name[10];
}s_stu,*p_stu;
甚至可以省略 struct 后面的stu
typedef struct{
int age;
int num;
char name[10];
}s_stu,*p_stu;
疑问1:
大家可以验证一下sizeof(struct stu)是多少, 貌似不是4+4+10 = 18 ,这里暂且放下,后面再讨论。
2.3 结构体变量访问及初始化
s_stu stu1;
p_stu p1;
p1 = &stu1; //p1存储stu1的地址
stu1.age = 1;
p1->num = 2;
(*p1).num = 3;//这里仅仅从语法层面上先理解 p1 = &stu1 , *p1 = stu1
比如数组的访问只能一个一个元素访问
char name[10];
name[0] = 'a';
name[1] = 'b';
而不能
name = {'a','b'};
放在结构体也同样使用,只不过前面放了 stu1. 或者 p->
stu1.name[0] = 'a';
stu2.name[1] = 'b';
p->name[2] = 'c';
p->name[3] = 'd';
获取成员的地址用以下方式
&stu1.age;
&p1->age;
对于一维数组来说 数组名可以代表第一个元素的地址,因此有以下代码
strcpy(name,"lilei");
放在结构体里就是
strcpy(stu1.name,"lilei");
或者
strcpy(p->name,“lilei”);
(3)以下写一个综合例子来使用结构体
int main(int argc,char* argv[])
{
//定义结构体变量要加上 struct 关键字。
struct stu stu1;
s_stu stu2;
p_stu p1,p2;
/*
结构体成员访问,结构体成员的使用跟单独使用一样,
只不过是多了stu1.xx;而且必须加上前缀 stu1.用来
标示是哪个结构体变量.
*/
p1 = &stu1;
stu1.num = 1;
stu1.age = 18;
/*
注意不要把这里写成 stu1.name = "stu1";
name是个数组,数组的赋值只能一个一个元素赋值。
*/
strcpy(stu1.name,"stu1");
//指针访问成员 用 ->
p2 = &stu2;
p2->num = 1;
p2->age = 18;
strcpy(p2->name,"stu2");
printf("num = %d\n",p1->num);
printf("age = %d\n",(*p1).age);
printf("name = %s\n",p1->name);
printf("num = %d\n",stu2.num);
printf("age = %d\n",stu2.age);
printf("name = %s\n",stu2.name);
return 0;
}
(4)结构体变量初始化
typedef struct stu{
int num;
int age;
char name[10];
}s_stu,*p_stu;
结构体变量初始化有以下两种方式:
省略成员名,成员的值必须与成员的顺序一致,之间用逗号隔开,最后一个成员可以不写逗号。
struct stu stu1 = {10,10,”stu1”};
初始化的时候可以只初始化前面的成员,而不初始化后面的成员,顺序不能变,后面的成员内存处全部为0。
/*
num 为 10
age 为 0
Name[0]~name[9]为0
*/
struct stu stu2 = {10,};
以下写法是不对的
struct stu stu3 = { 10,“123123”,};
加上成员名,注意成员名前有个“.”,成员的值必须与成员的顺序可以不一致,也可以省略。
struct stu stu2 = {
.age = 2,
.num = 2,
/*注意这里是数组的初始化*/
.name = “lilei”
};
struct stu stu3 = {
.age = 3,
.name = “jim”,
.num = 3
};
struct stu stu4 = {
.name = “tom”,
.num = 3
};
以下写代码验证
int main()
{
struct stu stu1 = {
10,10,"stu1"
};
struct stu stu2 = {
1,
};
struct stu stu3 = {
.num = 1,
.name = "stu3",
.age = 2
};
struct stu stu4 = {
.num = 1,
.age = 2,
.name = "stu4"
};
struct stu stu5 = {
.name = "stu5"
};
printf("num = %d\n",stu1.num);
printf("age = %d\n",stu1.age);
printf("name = %s\n",stu1.name);
printf("num = %d\n",stu2.num);
printf("age = %d\n",stu2.age);
printf("name = %s\n",stu2.name);
printf("num = %d\n",stu3.num);
printf("age = %d\n",stu3.age);
printf("name = %s\n",stu3.name);
printf("num = %d\n",stu4.num);
printf("age = %d\n",stu4.age);
printf("name = %s\n",stu4.name);
printf("num = %d\n",stu5.num);
printf("age = %d\n",stu5.age);
printf("name = %s\n",stu5.name);
return 0;
}