一、什么是结构体?
在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate data type)的一类。我们在程序里会创建很多变量,有时候我们需要用某个变量来描述一个人,而一个人身上的特点有很多,不止一个,如果只用一个特点来描述就显得不那么准确。所以我们要创建多个不同的变量来描述同一个人;而把这多个变量放在一起,起一个新名字就是结构体。
二、结构体的声明
在声明结构体时,必须列出它所包含的所有成员。这个列表包括每个成员的类型和名字。
struct student
{
char name[20];
char sex;
int number;
}stu;
这里声明了一个类型为struct student的结构体,并且创建了一个结构体变量stu,它包括三个成员:一个字符型数组,一个字符型变量,一个整形变量。
这里的student和stu可以根据情况省略掉其中一个。如果删掉类型名,后续不能再次定义此类型的结构体,如果删掉变量名则后续可以重新定义变量。
struct student
{
char name[20];
char sex;
int number;
}stu[20],*p;
这里在创建变量时创建了一个数组,数组的20个成员都是struct student类型的结构体,*p为可以指向该结构体类型的指针。
struct student1
{
char name[20];
char sex;
int number;
}stu;
struct student2
{
char name[20];
char sex;
int number;
}*p;
这里声明了两个结构体类型,其成员列表完全相同,但是其本质上是两个结构体,所以*p可以指向struct student2而不能指向struct student1;
三、创建结构体变量及初始化
struct student
{
char name[20];
char sex;
int number;
};
int main()
{
struct student stu = {"张三",'m',12};
return 0;
}
这里创建了stu变量并进行初始化。也可以对任意成员重新赋值。
stu.number = 10;
四、结构体与数组
结构体和数组都是聚合数据类型,不同的是数组存放的是相同的数据类型,而结构体存放的是不同的数据类型,那么,这两种类型是否可以存放各自的类型呢?答案是可以的,数组可以存放数组,也可以存放结构体,同时,结构体可以存放数组,也可以存放其他结构体。如
struct student1
{
char name[20];
char sex;
int number;
};
struct student2
{
char name[20];
char sex;
int number;
struct student1 stu;
};
那么,结构体是否能存放自身呢?
struct student1
{
char name[20];
char sex;
int number;
struct student1 stu;
};
答案是不可以的,因为在开辟空间时就会发现问题,当系统为结构成员struct student1 stu开辟空间时,发现他是另一个结构体,继而会对该结构体开辟空间而该结构体里又有结构体,陷入死循环,所以这是不成立的。
那如果我就是要一个可以存放自身结构体的元素呢?
struct student1
{
char name[20];
char sex;
int number;
struct student1 *p;
};
我们可以在结构体里定义一个指向自身类型的指针变量,而指针在64位平台下大小都是4字节,所以有效的避免了开辟空间的问题。
数组可以通过指针和下标访问元素,那结构体可以吗?
事实上结构体可以通过指针访问,但是不能通过下标访问。
五、结构体成员的访问
结构体访问方式有两种第一种直接通过变量名访问。
struct student
{
char name[20];
char sex;
int number;
};
int main()
{
struct student stu = { "张三",'m',12 };
printf("%s %c %d\n",stu.name,stu.sex,stu.number);
}
这里用到了“.”操作符,先是结构体变量名然后“.”接着是成员名;就可以访问对应元素。
第二种就是通过指针访问。
struct student
{
char name[20];
char sex;
int number;
}*p;
int main()
{
struct student stu = { "张三",'m',12 };
p = &stu;
printf("%s %c %d\n", p->name,p->sex,p->number);
}
这里用到“->”操作符,用指针来访问结构体成员。
六、结构体传参
结构体是标量,适用于其他标量可以使用的任何场合,因此把结构体作为参数传递给一个函数是合法的,但这种做法往往并不适宜。因为结构体里面往往包含多个成员,而我们知道函数传参会发生值拷贝,如果该结构体成员过多,这样的做法肯定会导致程序运行效率降低。所以正确的做法是指针传递。
struct student
{
char name[20];
char sex;
int number;
};
void fun(struct student *p)
{
printf("%s %c %d\n", p->name, p->sex, p->number);
}
int main()
{
struct student stu = { "张三",'m',12 };
fun(&stu);
return 0;
}
通过这样的方法就有效的避免了值拷贝问题。