一、结构体的声明
结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
1.结构的声明
struct tag
{
member-list;
}variable-list;
struct关键字 tag是结构体的标签名 struct tag合起来是结构体类型
大括号 {} 里放的是成员变量的列表,括号后面是变量列表
三种常见结构体的声明:
1:声明类型的同时可以不定义变量
struct Book
{
char name[20];
int price;
};
2:可以在括号后面创建结构体变量,注意这是全局变量
struct Book
{
char name[20];
int price;
}b3, b4, b5;
3:typedef类型重命名可以更方便我们使用结构体
typedef struct Book
{
char name[20];
int price;
}Book;
/ typedef之后想创建全局变量直接写在外面,而不是写在Book后面
Book b3;
Book b4;
2.结构成员的类型
结构的成员可以是标量、数组、指针,甚至是其他结构体。
struct S
{
char c;
char arr[10];
int* p;
}s1, s2;
struct S s3;
struct B
{
int a;
struct S s;
double d;
};
3.结构体变量的定义和初始化
struct Book
{
char name[20];
int price;
}b3, b4, b5;
int main()
{
struct Book b1;
struct Book b2;
return 0;
}
int a; 拿int类型创建一个a变量
拿结构体类型创建了一个b1变量就是struct Book b1;
也可以在创建类型的同时直接后面给名字
b3,b4,b5在大括号外部创建的,没有在函数内部,所以是全局的
初始化:定义变量的同时赋初值。
struct S
{
char c;
char arr[10];
int* p;
}s1, s2;
struct S s3;
struct B
{
int a;
struct S s;
double d;
}sb1, sb2;
struct B sb3;
int main()
{
struct S s4 = {'c', "zhangsan", NULL};/ 初始化
int a = 10;
struct B sb4 = { 100, {'q', "lisi", &a}, 3.14};/ 初始化
return 0;
}
struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = {10, {4,5}, NULL}; / 结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};/ 结构体嵌套初始化
二、结构体成员的访问
结构体变量.结构体成员 或者 结构体指针->结构体成员
struct Book
{
char name[20];
int price;
};
void print(struct Book* p)
{
printf("%s %d\n", p->name, p->price);
}
int main()
{
struct Book b1 = {"12345", 66};
struct Book b2 = { .price = 80, .name = "abcde"};
//结构体变量.结构体成员
printf("%s %d\n", b1.name, b1.price);
printf("%s %d\n", b2.name, b2.price);
//结构体指针->结构体成员
//struct Book* p1 = &b1;
print(&b1);
return 0;
}
三、结构体传参
struct S
{
int arr[1000];
int n;
};
void print1(struct S ss)
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", ss.arr[i]);
}
printf("\n%d\n", ss.n);
}
void print2(struct S* ps)
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", ps->arr[i]);
}
printf("\n%d\n", ps->n);
}
int main()
{
struct S s = { {1,2,3,4,5}, 100 };
print1(s);
print2(&s);
return 0;
}
上面的 print1 和 print2 函数哪个好些?
答案:print2函数。
原因:函数传参的时候,形参是实参的一份临时拷贝,参数是需要压栈的。 如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。
传结构体相当于传过去4004大小的数据,还要创建一模一样大小的空间,传递的数据量大,存储又得浪费空间,值传递空间和时间上都是浪费。
而指针也就4/8字节,指针变量接收,能用指针找到s就可以了,效率更高,指针还可以改数据,值传递只是使用无法更改原数据,想要指针不能修改原数据就用加const的指针接收
所以:结构体传参的时候,要传结构体的地址。