大家好,我是深鱼~
目录
【前言】:
一、结构体的声明
1.1结构的基本知识
1.2结构的声明
1.3结构体成员的类型
1.4结构体变量的定义和初始化
二、结构体成员的访问
【前言】:本章来介绍结构体的部分知识,并不会深入讲解,只是初阶部分,看得懂结构体的逻辑,并且会简单的运用,后期进阶部分还会深入讲解,希望对大家有所帮助
一、结构体的声明
1.1结构的基本知识
结构是一些值的集合,这些值称为成员变量,结构的每一个成员可以是不同类型的变量
这就让我们想起来数组:一组相同类型元素的集合
1.2结构的声明
struct tag //结构体关键字+名字(根据实际情况自己命名)
{
member-list; //成员变量的列表(一个或多个)
}variable-list //变量列表
为什么要出现结构体呢?
当前学习过的类型都是内置类型,eg:char,int,short,double...但是如果我们想要用一个类型来创建一个复杂对象,比如人:继续要名字+性别+年龄+电话+地址+...这时C语言就引进了结构体这个类型来创建复杂对象(对于一个变量,我们首先得有一个类型来创建这个变量,然后再把值存入变量中去)
假如我们要创建学生的变量:
学生类型——> 学生的变量——> 学生的属性信息
代码实现:
#include<stdio.h>
struct Stu
{
//学生的相关的属性
char name[20];
int age;
char sex[5];
char tele[12];
}s3,s4; //这里的s3,s4是变量名
struct Stu s5; //这样创建全局变量也是可以的
int main()
{
struct Stu s1; //注意这里类型是struct Stu(struct是不可以省略的)
struct Stu s2;
return 0;
}
上面一个创建了s1,s2,s3,s4,s5五个变量,但是s1,s2是局部变量,s3,s4,s5是全局变量
如果我们想要简化变量的类型:重命名
typedef struct Stu
{
//学生的相关的属性
char name[20];
int age;
char sex[5];
char tele[12];
}Stu; //Stu是重命名产生的新的类型
int main()
{
Stu s5;
return 0;
}
typedef是类型重定义,就是把类型的名字重命名
【注意】上一个代码中s3,s4是变量名,而这个代码中Stu是重命名产生的新类型
1.3结构体成员的类型
结构体成员可以是标量,数组,指针,甚至可以是其他结构体
代码演示:我们可以看到结构体成员还是比较丰富的
struct B
{
char c;
int i;
};
struct S
{
char c;
int num;
int arr[10];
double* pd;
struct B sb;
struct B* pb;
};
int main()
{
return 0;
}
1.4结构体变量的定义和初始化
定义:
全局变量的创建有两种:
(1)直接在结构体声明分号之前的加上变量名;
(2)在结构体声明结束后,跟局部变量创建一样些,但是不写在main函数中
初始化:
(1)按照顺序初始化:跟数组一样用{ },中间根据成员顺序输入进行初始化
(2)指定成员初始化:这样就得加上成员的名称eg:.num=1000,其他没有初始化的部分默认为0
代码演示如下:
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',1},NULL };//局部变量
//指定成员来初始化
struct S s4={.num=1000,.arr={1,2,3,4,5}};
return 0;
}
二、结构体成员的访问
·结构体变量.成员名
·结构体指针->成员名
代码演示:【写一个函数给s存放数据】
#include<string.h>
struct S
{
char name[20];
int age;
};
void set_s(struct S* ps)
{
(*ps).age = 18;
strcpy((*ps).name, "zhangsan");//字符串拷贝
//(*ps).name = "zhangsan";这是错误的,因为name是数组名,数组名是地址常量
}
int main()
{
struct S s = { 0 };
//写一个函数给s种存放数据
set_s(&s);
return 0;
}
这里要注意两个点:
(1)在name(数组成员)中存放数据的时候,我们不能像age一样直接存放:
因为name是数组名,数组名是地址常量,就相当于我们是把张三放到了一个门牌号上,并没有放入房间里,所以我们就用strcpy函数来存放数据
(2)在传参的时候不能直接传个过去,而要把s的地址(&s)传进去:
实参传给形参的时候,实参只是实参的一份临时拷贝,对形参的修改不会影响实参
上面是用结构体变量.成员名这个方法来存放数据的
其实也可以这样:指针直接指向成员名更好理解一点
ps->age=18;
strcpy(ps->name,"zhangsan");
下面再来【写一个函数打印s中的数据】:这里传参直接传结构体变量s就可以,只是打印不用带回main函数,其实这里传地址也可以,这其实也是更好的选择
struct S
{
char name[20];
int age;
};
void print_s(struct S t)
{
printf("%s %d\n", t.name, t.age);
}
void set_s(struct S* ps)
{
ps->age = 18;
strcpy(ps->name, "zhangsan");//字符串拷贝
}
int main()
{
struct S s = { 0 };
/*写一个函数给s种存放数据*/
set_s(&s);
//写一个函数打印s中的数据
print_s(s);
return 0;
}
【总结】:结构体传参的时候,要传结构体的地址
(1)当传参时传的是变量时,我们能做的事就很少,因为形参只是实参是一份临时拷贝,对形参进行操作并不改变实参;但是直接传地址过去,我们能干的就很多
(2)当我们传变量的时候,拷贝一份实参也是需要空间的;
而直接传地址,直接对原参数进行操作,不需要多余的空间,大大提高了效率
这次结构体的内容就到此啦,有什么问题欢迎评论区或者私信交流,觉得笔者写的还可以,或者自己有些许收获的,麻烦铁汁们动动小手,给俺来个一键三连,万分感谢 !