1.什么是结构体?
结构体是一些值的集合,这些值成为成员变量。结构体的每个成员变量可以是不同类型的变量。结构体一般是某类事物其属性的集合。例如,学生这个类型,通常会有,名字,学号,性别,年龄等。
2.结构体的声明
结构声明
struct tag{
member-list;
}variable-list;
结构体成员类型:
结构体的成员可以是标量,数组,指针,甚至是其他结构体
例如一个学生:
struct Stu{
char name[20];
int age;
char sex; //代码1
char id[10];
};
typedef struct Stu{
char name[20];
int age; //代码2
char sex;
char id[10];
}Stu;
代码1和代码2区别:
代码1声明结构体类型 struct Stu
代码2 typedef将声明的结构体类型struct Stu重定义为 Stu
特殊的声明
匿名结构体类型:在声明的时候省略了结构体标签(tag)
struct
{
char name[20];
int age;
char sex; //代码1
char id[10];
}x;
struct
{
char name[20];
int age; //代码2
char sex;
char id[10];
}a[20],*p;
问题:下述代码对吗?
p=&x;
答案:错误,只要是两个结构体类型,即便是里面元素完全一样,也是两种类型。
p=&a;
答案:正确,指向同一个结构体。
3.结构体的自引用
在结构体中包含一个类型为该结构体本身的成员是否可以呢?
struct Point {
int x; 代码1
struct Point p;
};
struct Point {
int x; 代码2
struct Point* p;
};
代码1,无法确定struct Point p的大小,错误
代码2,struct Point* p指针大小确定, 正确
typedef struct Point {
int x;
Point* p; 代码3
}Point;
typedef struct Point {
int x; 代码4
struct Point* p;
}Point;
代码3:错误
代码4:正确
4.结构体定义和初始化
struct Student { 结构体类型声明
char name;
int age;
}s1; 声明类型同时定义变量
struct Student s2; 定义结构体变量
struct Student s3 = { "zhangsan",20 };
初始化, 定义变量同时赋值
通过上述代码,则定义了3个结构体类型变量 s1, 声明类型同时定义变量。s2,定义结构体变量。 s3.初始化, 定义变量同时赋值
typedef struct Stu{
char name[20];
int age; //代码2
char sex;
char id[10];
}Stu;
Stu s1; //Stu == struct Stu
Stu s2={"lisi",18,m,20200114};
上述代码是关于重新定义结构体类型的结构体变量的定义和初始化。
struct Point {
int x;
int y;
};
struct Node {
int data;
struct Point p;
struct Node* n;
}n1 = { 10,{3,4},NULL }; 结构体嵌套初始化
struct Node n2;
struct Node n3 = { 20,{5,6},NULL }; 结构体嵌套初始化
上述代码是关于结构体嵌套的初始化用法
5.结构体成员访问
1.结构体变量访问成员:通过使用点操作符(.)访问。
struct Stu { //结构体类型声明
char name[10];
int age;
};
struct Stu s;
strcpy(s.name, "zhangsan");
s.age = 20;
printf("%s %d\n", s.name, s.age);
2.结构体指针访问其指向变量的成员 (->)操作符
struct Stu { //结构体类型声明
char name[10];
int age;
};
struct Stu s = {"zhangsan",20};
struct Stu *p = &s;
printf("%s %d\n", s.name, s.age);
printf("%s %d\n", (*p).name, (*p).age);
printf("%s %d\n", p->name, p->age);
上述代码中:
1.(*p).name 等价于 s.name 。p是一个结构体指针,指向s变量,指针解引用代表其所指向的元素s。
2. 使用结构体指针访问指向变量的成员 p->name
6.结构体传参
结构体传参会不会发生降维问题?不会
使用print1还是print2?
struct Student {
char name[10];
int age;
};
struct Student s = { "xiaoming",10 };
void print1(struct Student s) {
printf("%s %d\n", s.name,s.age);
}
void print2(struct Student *p) {
printf("%s %d\n", p->name,p->age);
}
int main() {
print1(s); 传结构体
print2(&s); 传地址
return 0;
}
函数传参时,参数是需要压栈,会有时间和空间的开销。
如果传入一个结构体对象时,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。
结论:结构体传参时,要传结构体的地址。