7.结构体
7.1 结构体
类型的声明
7.1.1 介绍
结构体是由一批数据组合而成的结构型数据。组成结构型数据的每个数据称为结构型数据的“成员”,其描述了一块内存区间的大小及解释意义。
- 结构体是一种数据类型,地位同等于int、float等
- 结构体类型不是系统定义好的,由程序员自己定义
- 使用struct关键字来标识定义的结构体类型
- 结构体通常用来表示类型不同但又相关的若干数据
- 关键字struct和结构体名组成类型标识符
- 成员又称为成员变量,是结构体所包含的若干个基本的结构类型
- 结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针
7.1.2 声明
// 格式:
struct tag {
member-list
member-list
member-list
...
} variable-list;
// tag: 结构体标签
// member-list: 变量定义
// variable-list: 结构体变量
// 一般情况下:tag、member-list、variable-list 3部分至少出现两个
// 使用typedef创建新类型
typedef struct
{
int a;
char b;
double c;
} Simple;
// 可以用Simple作为类型声明新的结构体变量
// eg:
Simple s;
7.1.3 例
int main()
{
struct Person
{
char name[10];
short age;
};
struct Student
{
char id[20];
struct Person p;
};
return 0;
}
7.2 结构体初始化
7.2.1 定义时初始化
int main()
{
struct Person
{
char name[10];
short age;
};
struct Student
{
char id[20];
struct Person p;
} s = {"1914121006", {"listen", 25}};
return 0;
}
7.2.2 定义后初始化
struct Person
{
char name[10];
short age;
};
struct Student
{
char id[20];
struct Person p;
};
int main()
{
struct Student s = { "1914121006", {"listen", 25} };
return 0;
}
7.3 结构体成员访问
7.3.1 .
struct Person
{
char name[10];
short age;
};
struct Student
{
char id[20];
struct Person p;
};
int main()
{
struct Student s = { "1914121006", {"listen", 25} };
printf("id: %s\nname: %s\nage: %d\n", s.id, s.p.name, s.p.age);
return 0;
}
7.3.2 →
struct Person
{
char name[10];
short age;
};
struct Student
{
char id[20];
struct Person p;
};
int main()
{
struct Student s = { "1914121006", {"listen", 25} };
struct Student* ps = &s;
printf("id: %s\nname: %s\nage: %d\n", (*ps).id, (*ps).p.name, (*ps).p.age);
printf("id: %s\nname: %s\nage: %d\n", ps->id, ps->p.name, ps->p.age);
return 0;
}
7.4 结构体传参
struct Person
{
char name[10];
short age;
};
struct Student
{
char id[20];
struct Person p;
};
void print1(struct Student s)
{
printf("id: %s\nname: %s\nage: %d\n", s.id, s.p.name, s.p.age);
}
void print2(struct Student* ps)
{
printf("id: %s\nname: %s\nage: %d\n", ps->id, ps->p.name, ps->p.age);
}
int main()
{
struct Student s = { "1914121006", {"listen", 25} };
print1(s); // 值传递
print2(&s); // 址传递
return 0;
}
- print1和pirnt2对比:
- print1: 值传递,更安全。传参时,需要开辟一块与结构体变量s同等大小的区域用于将s复制一份到print1函数中,相比于print2消耗更多的内存资源。此外,print1函数中不可以修改结构体变量s中的值。
- print2: 址传递。传参时,在32位平台使用4字节内存资源,在64位平台使用8字节。相比于print1,消耗更少的内存资源。此外,print2可以修改结构体变量s中成员变量的值。但print2相对于print1不安全。
函数传参的时候,参数是需要压栈的,并且按照参数列表的顺序,从右向左压栈。如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。
结论:结构体传参时,要传结构体的指针。