结构体
1.结构体的定义
结构体是成员变量的集合
struct book//书 *结构体类型名*
{
char name[20];//书名
char author[15];//作者
float price;//价格
}b1,b2; //全局变量
int main()
{
struct book b; //在main函数里定义的是局部变量
return 0;
}
当然如果我们把结构体类型声明在main函数内部也可以。但在团队合作中更多是团队一起使用,所以定义在外面更好。
还有一种方法是使用typedef对类型重定义,如:
typedef struct human
{
char name[20];
int age;
char sex[10];
char id[20];
}hu;
int main() {
struct human man; //1.
hu man; //2.
return 0;
}
这样该结构体就有了两种创建变量的方式,struct human man和hu man都行。当然使用typedef就不能在声明结构体的后面直接创建全局变量了。
结构体类型是不占用空间的,只有创建变量时才会开辟空间。
2.结构体变量的定义
可以直接在结构体声明后面定义,甚至在后面可以初始化。
struct book
{
char name[20];
char author[15];
float price;
}b1, b2;
struct book b3 = { 0 };
struct point {
int x;
int y;
};
struct point p1 = { x, y };
3.结构体成员的访问
3.1 . 操作符
左边是结构体变量名,右边是结构体成员名。
3.2 -> & * 操作符
当然有的时候有可能我们得到的是一个指向该结构体的指针。这时候我们就需要操作符->,同样也是两个操作数
struct T t = { {10, 'x', 1.00}, "yourfriendyo", 21 };
//1.
struct T* pt = &t;
printf("%d %c %lf %s %d\n", (*pt).s.a, (*pt).s.c, (*pt).s.d, (*pt).name, (*pt).num);
//2.
printf("%d %c %lf %s %d\n", pt->s.a, pt->s.c, pt->s.d, pt->name, pt->num);
//3.
struct S* ps = &(t.s);
printf("%d %c %lf %s %d\n", ps->a, ps->c, ps->d, pt->name, pt->num);
4.结构体作参数
struct S {
char arr[100];
int num;
float f;
};
void Print(struct S ss) {
printf("%c %c %c %d %f\n", ss.arr[0], ss.arr[1], ss.arr[2], ss.num, ss.f);
}
void Print2(struct S* ps) {
printf("%c %c %c %d %f\n", ps->arr[0], ps->arr[1], ps->arr[2], ps->num, ps->f);
}
int main() {
struct S s = { {'1','2','3','4'}, 22, 3.14};
Print1(s);
Print2(&s);
return 0;
}
既然讨论到函数传参,就会有传址调用和传址调用的问题。
如上述代码,我们直接把 s 传过去,显然是传值调用,但 s 本身就占用了非常大的空间,然后又创建了一份一样大的形参临时拷贝,时间空间上浪费的问题非常严重。这样的话,很明显我们还是传址调用最好,无论 s 的占用有多大,我们只传了4个字节的地址。
所以结构体传参通常使用传址调用。