一、 结构体的基础知识
- 结构是一些值的集合,这些值称为成员变量
- 结构的每个成员可以是不同类型的变量
(1)结构体的声明
写法一:
注:
- 括号后边的分号不能忘
- 结构体末尾可以不创建变量,在主函数中再创建
struct Book
{
char name[20]; //书名
int price; //价格
};
写法二:
注:
- 在结构体末尾和主函数中都可以创建变量
- 区别:结构体后边直接创建的是全局变量,在主函数中创建的是局部变量
写法三:
注:
- 可以利用 typedef 重命名或定义结构体
- 若使用 typedef 定义,则结构体末尾不能创建全局变量,而应该写结构体新的名称,新名称后边的分号不能丢失
- 若非要创建全局变量,需单独创建
- 此处,新的结构体名称 Book 代替的是 struct Book 这一整体,在创建结构体变量时,可直接写
Book b5;
来代替struct Book b5;
typedef struct Book
{
char name[20];
int price;
}Book; //不可以创建全局变量,此处是新的结构体名
//如果实在想使用全局变量,需单独创建
Book b3;
Book b4;
int main()
{
struct Book b1;
struct Book b2;
Book b5;
Book b6;
return 0;
}
(2)结构成员的类型
- 结构的成员可以是标量、数组、指针,甚至是其他结构体
struct S
{
char c;
char arr[10];
int *p;
};
struct B
{
int a;
struct S s;
double d;
};
int main()
{
return 0;
}
(3)结构体变量的初始化
例1:
struct S
{
char c;
char arr[10];
int* p;
};
struct B
{
int a;
struct S s;
double d;
};
int main()
{
struct S s1 = { 'c',"张三",NULL }; //初始化
int a = 10;
struct B s2 = { 100,{'q',"list",&a},3.14 }; //结构体嵌套初始化
return 0;
}
例2:
- 初始化时可以按顺序初始化,也可以不按顺序
struct Book
{
char name[20];
int price;
};
int main()
{
//按顺序初始化
struct Book b1 = {"鹏哥C语言", 66};
//不按顺序初始化
struct Book b2 = { .price = 80, .name = "杭哥C++"};
//打印
printf("%s %d\n", b1.name, b1.price);
printf("%s %d\n", b2.name, b2.price);
return 0;
}
二、 结构体成员的访问
访问结构体成员的方式:
- 结构体变量 . 结构体成员
- 结构体指针 -> 结构体成员
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
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 = {"鹏哥C语言", 60};
struct Book b2 = { .price = 80, .name = "杭哥C++"};
struct Book b3 = { "JAVA",70 };
//结构体变量.结构体成员
printf("%s %d\n", b1.name, b1.price);
printf("%s %d\n", b2.name, b2.price);
//结构体指针->结构体成员
struct Book* p1 = &b3;
print(p1); //结构体地址传参
return 0;
}
三、结构体传参
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
struct S
{
int arr[100];
int n;
};
void print1(struct S ss)
{
for (int i = 0; i < 10; i++)
{
printf("%d ", ss.arr[i]);
}
printf("\n%d\n", ss.n);
}
void print2(struct S* ps)
{
for (int 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 函数。
原因:
- 函数传参的时候,参数是需要压栈的。如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。
结论:
- 结构体传参的时候,要传结构体的地址。