结构体类型的声明
结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
下面是描述一个学生信息的结构体
这里的struct可以理解为类型,Stu就是变量名
typedef是类型定义的意思。typedef struct 是为了使用这个结构体方便。能够省去struct这个关键字。
结构体可以去描述复杂的对象,例如我们的个人信息(名字、性别、年龄、电话、地址)。
结构体初始化
案例如下
#include <stdio.h>
struct b
{
char c;
int i;
};
struct s
{
char c;
int num;
int arr[10];
double* pd;
struct b sb;
struct b* pb;//可以在结构体里面再嵌套一个指向另一个结构体的指针
}s1;//s1是全局变量
struct s s2;//s2是全局变量
int main()
{
double d = 3.14;
//按照顺序初始化
struct s s3 = { 'q', 100, {1,2,3}, &d, {'a', 99},NULL};//局部变量
//指定成员来初始化
struct s s4 = { .num = 1000, .arr = {1,2,3,4,5} };//局部变量
return 0;
}
在不同位置定义结构体变量,是会产生不一样的效果的,有全局变量也有局部变量。
初始化结构体有两种办法,一种就是按顺序初始化结构体。
另一种就是(" . " + 成员名),来初始化结构体。
结构体成员访问
下面是我对结构体成员的赋值过程,还有对结构体访问,我用到了两种方法对结构体访问。
#include <string.h>
struct S
{
char name[20];
int age;
};
void set_s(struct S* ps)
{
ps->age = 18;
//t.name = "zhangsan";//不能用这种写法,因为name是数组名,数组名是常量的地址
strcpy(ps->name, "zhangsan");//字符串拷贝
}
void print_s1(struct S* ps)
{
printf("%s %d\n", ps->name, ps->age);
}
void print_s2(struct S ps)
{
printf("%s %d\n", ps.name, ps.age);
}
int main()
{
struct S s = {0};
//写一个函数给s中存放数据
set_s(&s);
//打印s中的数据
print_s1(&s);
print_s2(s);
return 0;
}
第一种访问方法就是(&+结构体变量名),把结构体的地址传给函数,在函数里面,使用(结构体变量名->成员名) 打印内容。
第二种访问方法就是传结构体变量名给函数,然后使用(结构体变量名.成员名) 打印内容。
上面的代码中有句错误的代码,如下
t.name = “zhangsan”;
因为name是数组名,数组名不是一个左值,即不是一个可以被赋值的实体。
字符串字面量(“zhangsan”)在C语言中是存储在只读内存区域的常量。尝试将一个字符串字面量赋值给数组名实际上是尝试将一个常量地址赋值给数组名,这在C语言中是不允许的。
结构体传参
在上面的结构体成员访问的那部分内容,你有没有发现我既可以传结构体变量的地址给函数,也可以直接传结构体变量名给函数。
(&+结构体变量名)就是传结构体的地址
还有就是直接传结构体变量名
两种不同的传参方式也带了不一样的效果。
函数传参的时候,参数是需要压栈的
如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。你传结构体地址的话,就不用再开辟新的空间,不仅提高效率还省时间。
所有结构体传参的时候,要传结构体的地址。(&+结构体变量名)