目录
前言
3.1结构体的含义以及语法
3.1.1结构体含义
3.1.2结构体语法形式
3.1.2结构体变量的创建和初始化
3.2结构体成员的类型
3.3结构体的成员访问
3.3.1.操作符
3.3.2->操作符
3.4结构体传参
前言
小伙伴们大家好!欢迎继续和菜菜酱学习c语言呐!之前菜菜酱有事所以耽误啦,废话不多说,让我们一起开始今天的学习叭!
3.1结构体的含义以及语法
3.1.1结构体含义
结构是一些值的集合,这些值称为成员变量。结构体变量的每个成员可以是不同类型的变量这怎么么进行理解呢?大家还记得数组的含义吗?数组是一组相同类型的集合,而结构体是一组不同类型的集合!那么为什么要使用结构体呢?这是因为内置变量无法描述复杂情况,在生活中描述一个人需要年龄,性别,名字等等!接下来一起看看结构体的语法形式叭!
3.1.2结构体语法形式
struct tag
{
member-list;
}varaible-list;
解释:tag可以任意命名,struct tag组合成结构体标签。member-list是成员变量一般用来描述结构体对象的相关属性,varaible-list是全局变量。这整个共同组成结构体类型。用代码来看看叭!
struct stu
{
int age;
char name[20];
char sex[5];
};
3.1.2结构体变量的创建和初始化
还是以描述一个为例来看看怎么创建变量叭!
struct stu
{
int age;
char name[10];
char sex[5];
}s2;//第二种方式
struct stu s1;//第一种方式
int main()
{
//第3种方式
struct stu s3;
return 0;
}
现在变量已经创建好了,但是我们会发现这个类型写起来好麻烦有没有什么办法可以简化呢?酱酱们还记得typedef吗?typdedef可以对类型进行重命名,
typedef unsigned int unit
这个代码的意思是把unsigned int 重命名为unit,但是结构体的重命名不是这种写法!
typedef struct stu
{
member-list;
}stu;
typedef对结构体的重命名是把重命名部分放在大括号后面分号前面!注意此时stu不再是列表变量而是重命名!此时再写结构体类型需要写stu即可不需要再写struct!在c语言中没有对结构体进行typedef,struct关键字不能省略
该怎么进行初始化呢?还记得数组是怎么经行初始化的吗?没错利用大括号,结构体的初始化也是利用结构体!上代码一起来看看叭
struct stu
{
int age;
char name[10];
char sex[5];
};
int main()
{
struct stu s = { 20,'张三','男'};
return 0;
}
3.2结构体成员的类型
结构体成员的类型可以是标量,数组,指针,甚至是结构体!
struct stu
{
float price;
char name[20];
struct stu1;
int* p;
};
struct stu1
{
int age;
int* pa;
int name[10];
};
int main()
{
struct stu s1;
struct stu1 s;
return 0;
}
以上的代码包含了可能出现的所有情况。但是要是结构体的成员变量是结构体此时该怎么进行初始化呢?还是和之前一样噢,来看看叭
struct stu
{
float price;
char arr[20];
struct stu1;
int* p;
};
struct stu1
{
int age;
int* p;
char arr1[10];
};
int main()
{
struct stu s = { 80.2,'张三',{20,NULL,"bit"},NULL };
return 0;
}
3.3结构体的成员访问
在初识c语言时我们就介绍了结构体成员访问操作符.和->,现在让我们一起来仔细了解了解叭
3.3.1.操作符
具体怎么使用,直接上代码看看叭
struct stu
{
int age;
char sex[5];
char name[10];
};
int main()
{
struct stu s1 = { 20,"男","张三" };
printf("%d %s %s", s1.age, s1.sex, s1.name);
return 0;
}
总结一下.操作符的具体使用:结构体类型.结构体成员
3.3.2->操作符
还记得前面的介绍吗?->适用于结构体指针,再来代码看看叭!还是以介绍一个人对的年龄姓名为例,不过不同的是利用一个函数来其初始化和打印!上代码
#include<string.h>
struct stu
{
int age;
char name[10];
};
void set_stu(struct stu t)
{
t.age = 20;
strcpy(t.name, "张三");
}
void print(struct stu t)
{
printf("%d %s", t.age, t.name);
}
int main()
{
struct stu s1 = {0};
set_stu(s1);
print(s1);
return 0;
}
这是我们立马想到的解决办法,乍看上去貌似没有什么错误,但是运行起来就发现问题了
为什么打印出来0呢?这是因为在进行函数调用时使用了传值调用,此时形参是实参的一份临时拷贝,对形参的修改并不会影响实参。此时我们不应该用传值调用而是用传址调用,传结构体的地址
struct stu
{
int age;
char name[10];
};
void set_stu(struct stu* t)
{
//(*t).age = 20;
//strcpy((*t).name, "张三");
t->age=20;
strcpy(t->name,"张三");
}
void print(struct stu t)
{
printf("%d %s", t.age, t.name);
}
int main()
{
struct stu s1 = { 0 };
set_stu(&s1);
print(s1);
return 0;
}
此时就可以成功打印了
总结一下:结构体指针->结构体成员
3.4结构体传参
在上面的学习中我们能发现结构体传参分为两种,传值和传址!上代码
struct stu
{
char name[10];
char sex[4];
int age;
int weight;
};
void print(struct stu s1)
{
printf("%s %s %d %d\n", s1.name, s1.sex, s1.age, s1.weight);
}
void set(struct stu* s2)
{
strcpy(s2->name, "张三");
strcpy(s2->sex, "男");
s2->age = 23;
s2->weight = 200;
}
int main()
{
struct stu s1 = { "张三","男",26,140 };
print(s1);//传值
struct stu s2 = { 0 };
set(&s2);//传地址
printf("%s %s %d %d\n", s2.name, s2.sex, s2.age, s2.weight);
return 0;
}
传值时用.操作符,传址时用->操作符!结构体传参有两种选择哪种更合适·呢·?答案是使用传地址的更好!
原因:
- 函数传参时需要压栈
- 如果传递下一个结构体对象的时候结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降
结论:
结构体传参时,要传结构体的地址
关于更多结构体的内容在后面的学习中会介绍,今天的学习到此为止啦!