• 解锁C语言结构体的力量(初阶)


    引言:在实际生活中我们不可能遇到的都是简单变量,大部分情况都是复杂变量,所以今天我们走进C语言中关于复杂变量的世界——结构体。


    目录

    结构体的概念:🤔

    结构体类型的声明:🤔

    结构体初始化:🤔

    结构体成员访问和传参:

    两种形式:

    🌟🌟🌟形参只是实参的一份临时拷贝,形参的改变不影响实参。

    思考:🤔


     

    结构体的概念:🤔

    在之前学习数组的时候,我们知道数组是由相同元素组成的集合,而结构体则是不同元素构成的集合,每个元素我们称他为“成员变量”,在C语言中,结构体由多个成员变量组成,每个成员变量可以是不同的数据类型,比如整数、浮点数、字符数组等。通过使用结构体,可以将这些不同类型的数据组织在一起,形成一个逻辑上相关的数据集合

    比如:书 = 书名 + 价格 + 作者 + 类型 + .......

    这种就是复杂对象,就可以用结构体来定义它🌻🌻🌻


     

    结构体类型的声明:🤔

    1. #include
    2. struct Stu
    3. {
    4. //学生的相关属性
    5. char name[20];
    6. int age;
    7. char sex[5];
    8. char tele[12];
    9. } s3, s4;
    10. //s3,s4是结构体类型的变量
    11. //s3,s4是全局的
    12. int main()
    13. {
    14. struct Stu s1;
    15. struct Stu s2;
    16. //s1,s2是结构体类型的变量,是局部变量
    17. return 0;
    18. }

    这里面的是s1、s2、s3、s4都是结构体类型的变量,区别就是s1、s2是局部变量,s3,s4是全局变量。

    注意:main里面的struct是绝对不能省略掉的

    但是如果我们在定义结构体的时候加上typedef

    1. typedef struct Stu
    2. {
    3. //学生的相关属性
    4. char name[20];
    5. int age;
    6. char sex[5];
    7. char tele[12];
    8. }Stu;
    9. int main()
    10. {
    11. Stu s5;
    12. return 0;
    13. }

    而重命名产生的Stu是新的类型,这样就可以省略struct了,后面用起来就会变得方便一些。🌞🌞🌞


     

    结构体初始化:🤔

    我们不仅可以进行顺序初始化,也可以指定成员初始化,如果没有成员被初始化,那么就会被系统默认为0,或者是NULL。

    1. #include
    2. struct B
    3. {
    4. char c;
    5. int i;
    6. };
    7. struct S
    8. {
    9. char c;
    10. int num;
    11. int arr[10];
    12. double* pd;
    13. struct B sb;
    14. struct B* pb;
    15. }s1;//s1是全局变量
    16. struct S s2;//s2是全局变量
    17. int main()
    18. {
    19. double d = 3.14;
    20. //按照顺序初始化
    21. struct S s3 = { 'q', 100, {1,2,3}, &d, {'a', 99}, NULL };//局部变量
    22. //指定成员来初始化
    23. struct S s4 = { .num = 1000, .arr = {1,2,3,4,5} };//局部变量
    24. return 0;
    25. }

     这里的调试结果也可以看到成功进行了初始化。

    值得注意的是:如果成员变量也是结构体变量的话那么我们可以在加上一个大括号,并且将其初始化。🌈🌈🌈


     

    结构体成员访问和传参:

    两种形式:

    1️⃣结构体变量.成员名

    2️⃣结构体指针->成员名

    1. #include
    2. #include
    3. struct S
    4. {
    5. char name[20];
    6. int age;
    7. };
    8. void set_s(struct S t)
    9. {
    10. t.age = 18;
    11. //t.name = "zhangsan";//err,因为name是数组名,数组名是常量的地址
    12. strcpy(t.name,"zhangsan");//字符串拷贝
    13. }
    14. void print_s(struct S* ps)
    15. {
    16. printf("%s %d\n", ps->name, ps->age);
    17. }
    18. int main()
    19. {
    20. struct S s = {0};
    21. //写一个函数给s中存放数据
    22. set_s(s);
    23. //写一个函数打印s中的数据
    24. print_s(&s);
    25. return 0;
    26. }

    这个代码里面有两个点值得我们注意:

    1️⃣这个输出结果为什么是0而不是我们传给他的值?🤔🤔🤔

    2️⃣为什么赋值zhangsan的时候要用strcpy库函数?🤔🤔🤔

    答:首先解答strcpy,因为我们要给.name赋值,而zhangsan是一个字符串,所以我们给字符串赋值的时候不能直接用=,要用strcpy这个库函数。

    而对于为什么是0我们用张图来解答

    🌟🌟🌟形参只是实参的一份临时拷贝,形参的改变不影响实参。

    正确的代码:

    1. #include
    2. #include
    3. struct S
    4. {
    5. char name[20];
    6. int age;
    7. };
    8. void set_s(struct S* ps)
    9. {
    10. (*ps).age = 18;
    11. //t.name = "zhangsan";//err,因为name是数组名,数组名是常量的地址
    12. strcpy((*ps).name,"zhangsan");//字符串拷贝
    13. }
    14. void set_s(struct S* ps)
    15. {
    16. ps->age = 18;
    17. //t.name = "zhangsan";//err,因为name是数组名,数组名是常量的地址
    18. strcpy(ps->name,"zhangsan");//字符串拷贝
    19. }
    20. void print_s(struct S* ps)
    21. {
    22. printf("%s %d\n", ps->name, ps->age);
    23. }
    24. int main()
    25. {
    26. struct S s = {0};
    27. //写一个函数给s中存放数据
    28. set_s(&s);
    29. //写一个函数打印s中的数据
    30. print_s(&s);
    31. return 0;
    32. }

    代码里的(*ps).ageps->age是一样的,也体现了我们刚刚说的访问结构体变量的两种形式。🌅🌅🌅


     

    思考:🤔

    1. void print1(struct S* ps)
    2. {
    3. printf("%s %d\n", ps->name, ps->age);
    4. }
    5. void print2(struct S ps)
    6. {
    7. printf("%s %d\n", ps.name, ps.age);
    8. }
    9. int main()
    10. {
    11. struct S s = {0};
    12. //写一个函数给s中存放数据
    13. set_s(&s);
    14. //写一个函数打印s中的数据
    15. print1(&s);
    16. print2(s);
    17. return 0;
    18. }

    问: 在这个代码中,print1和print2都可以正确的打印出struct  s,那么哪一个更好呢?

    答:printf1更好

    1️⃣print1能做的事更多,如果我们在函数中需要改变这个结构体变量,那么只有取地址才能改变他的值,而print2则不能随意改变.

    2️⃣print2相当于又开辟了一个新的结构体变量来储存,变相的相当于消耗了更多的空间,而还需要将结构体里的成员一个个都传过去,有变相的消耗了时间,所以没有print1好.

  • 相关阅读:
    Java Package用法:组织与管理类的利器
    在项目中如何利用JS去修改CSS的属性值(二) --- :root+var()方法
    docker-machine常用
    行业现状?互联网公司为什么宁愿花20k招人,也不愿涨薪留住老员工~
    一个AI板卡电脑--香橙派 AIpro
    Java CountDownLatch 学习总结
    【网络通信 -- WebRTC】项目实战记录 -- mediasoup android 适配 webrtc m94
    5. SAP ABAP OData 服务如何支持 $filter (过滤)操作
    CRM客户管理系统源码 带移动端APP+H5+小程序
    redis的三种启动方式(后台运行)
  • 原文地址:https://blog.csdn.net/2301_77125473/article/details/133242190