本篇是对结构体进行一个初步的学习。共分为以下四个部分。
1.结构体类型的声明
2.结构体初始化
3.结构体成员的访问
4.结构体传参
1.结构体类型的声明
我们在生活中要描述的对像一般都是复杂对象,比如说我想描述一个人,那么我们就要描述这个人的性别,年龄,身高,体重等等,也就是说,我们无法用一个简单的值来描述他。在c语言中,如果我们也想要描述这样的复杂变量,那么我们就可以用结构体。
结构是一些值的集合,这些值成为成员变量,结构的每个成员都可以是不同类型的变量。
那么如何来创建一个结构体变量呢,首先我们要对这个结构体类型进行声明。
struct Book
{
char name[20];
int price;
};
这样我们就声明了一个结构体类型,类型名为struct Book。
当我们声明好了一个结构体类型,该如何使用它呢?我们看下面的代码。
struct Book
{
char name[20];
int price;
};
int main()
{
struct Book b;//我们就利用了结构体类型struct Book创建了一个结构体变量b
//b.name="c语言";我们不能使用这种之间赋值的方式,因为name是数组
strcpy(b.name."c语言");//给数组赋值应该用函数strcpy
b.price=55;
printf("%s\n",b.name);
printf("%d\n",b.price);
return 0;
}
这里的b就是我们创建的结构体变量,我们也可以创建多个结构体变量
struct Book
{
char name[20];
int price;
}b4,b5,b6;
int main()
{
struct Book b1;
struct Book b2;
struct Book b3;
strcpy(b.name."c语言");
b.price=55;
printf("%s\n",b.name);
printf("%d\n",b.price);
return 0;
}
如上面的代码,我创建了b1~b6六个结构体变量,他们之间不同的就是b1,b2,b3是局部变量,b4,b5,b6是全局变量
此外,我们还有一种创建结构体变量的方法
typedef struct Book
{
char name[20];
int price;
}Book;
int main()
{
Book b1;
struct Book b2;
strcpy(b.name."c语言");
b.price=55;
printf("%s\n",b.name);
printf("%d\n",b.price);
return 0;
}
就是用typrdef把结构体类型重命名,我是把结构体类型重命名成了Book,在创建结构体变量时用struct Book或者Book都可以。
值得说明的是:在我们声明结构体时,内存并不会分配空间,只有当我们创建了结构体变量时,内存才会给里面的成员分配空间。
结构体成员可以是标量,数组,指针,甚至是其他结构体。
2.结构体变量的初始化
结构体变量的初始化与数组类似,用一个大括号,在里面对成员挨个初始化。
struct Book
{
char name[20];
int price;
};
int main()
{
struct Book b={"c语言",55};
return 0;
}
3.结构体成员的访问
主要是使用两个操作符
. 结构体变量.成员名
-> 结构体指针->成员名
下面我们就来看看这两种访问的用法
struct Book
{
char name[20];
int price;
};
void print1(struct Book b)
{
printf("%s %d\n",b.name,b.price);
}
void print2(struct Book* pb)
{
printf("%s %d\n",(*pb).name,(*pb).price);
printf("%s %d\n",pb->name,pb->price);
}
int main()
{
struct Book s={"c语言",55};
print1(s);
print2(&s);
return 0;
}
我们创建了两个打印函数,分别用结构体变量s的值与地址完成了对s的成员的打印,print1就是传值调用,print2就是传址调用。而这两种调用的过程其实是有不一样的,在print1中,形参b其实是对s的一份临时拷贝,在打印是调用的也是b里的成员,但是在print2中就不一样,传给print2的是s的地址,所以实现打印时是打印的结构体变量s本身。
4.结构体传参
在上面的代码中,我们有两种传参方式,那么哪种方式会好一些呢?
当结构体进行传值调用时,会在内存中又临时拷贝一份,这就会造成空间的浪费,系统开销变大。当我们使用传址调用时,我们只需要把地址传过去,会节省空间,提高程序的效率。
函数传参时,参数是需要压栈的,如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,会导致性能下降,所以在传参时,我们要优先考虑传址调用。