• [C语言] 结构体


    结构体类型的声明
    结构体初始化
    结构体成员访问
    结构体传参

    目录

    1. 结构体的声明

    1.1 结构的基础知识

    1.2 结构的声明

    1.3 结构成员的类型

    1.4 结构体变量的定义和初始化

    2. 结构体成员的访问

    3. 结构体传参


    1. 结构体的声明

    1.1 结构的基础知识

    数组:一组相同类型的元素的集合。

    结构体:也是一些值的集合,但是值的类型可以不同。

    结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。

    1.2 结构的声明

    struct tag
    {
             member - list ;
    variable - list ;
    例如描述一个学生:
    typedef struct Stu
    {
              char name [ 20 ]; // 名字
              int age ; // 年龄
              char sex [ 5 ]; // 性别
              char id [ 20 ]; // 学号
    } Stu // 分号不能丢

    1.3 结构成员的类型

    结构的成员可以是标量、数组、指针,甚至是其他结构体。

    1.4 结构体变量的定义和初始化

    有了结构体类型,那如何定义变量,其实很简单。

    1. struct B
    2. {
    3. char c;
    4. short s;
    5. double d;
    6. };
    7. struct Stu
    8. {
    9. //成员变量
    10. struct B sb;
    11. char name[20];//名字
    12. int age;//年龄
    13. char id[20];
    14. }s1,s2;//s1和s2也是结构体变量 相当于s
    15. //s1,s2是全局变量
    16. int main()
    17. {
    18. //s是局部变量
    19. struct Stu s = { {'w',20,3.14},"张三",30,"202005034" };//对象 初始化
    20. //. ->
    21. /*printf("%c", s.sb.c);
    22. printf("%s\n", s.id);*/
    23. struct Stu* ps = &s;
    24. printf("%c\n", (*ps).sb.c);
    25. printf("%c\n", ps->sb.c);
    26. return 0;
    27. }
    1. struct Point
    2. {
    3. int x;
    4. int y;
    5. }p1; //声明类型的同时定义变量p1
    6. struct Point p2; //定义结构体变量p2
    7. //初始化:定义变量的同时赋初值。
    8. struct Point p3 = {x, y};
    9. struct Stu        //类型声明
    10. {
    11. char name[15];//名字
    12. int age;      //年龄
    13. };
    14. struct Stu s = {"zhangsan", 20};//初始化
    15. struct Node
    16. {
    17. int data;
    18. struct Point p;
    19. struct Node* next;
    20. }n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
    21. struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化

    2. 结构体成员的访问

    结构体变量访问成员
    结构变量的成员是通过点操作符(.)访问的。点操作符接受两个操作数。
    例如:
    我们可以看到 s 有成员 name age
    那我们如何访问 s 的成员?
    struct S s;
    strcpy(s.name, "zhangsan");// 使用 . 访问 name 成员
    s.age = 20;// 使用 . 访问 age 成员
    结构体指针访问指向变量的成员
    有时候我们得到的不是一个结构体变量,而是指向一个结构体的指针。
    那该如何访问成员。

    如下:

    1. struct Stu
    2. {
    3. char name[20];
    4. int age;
    5. };
    6. void print(struct Stu* ps)
    7. {
    8. printf("name = %s   age = %d\n", (*ps).name, (*ps).age);
    9.    //使用结构体指针访问指向对象的成员
    10. printf("name = %s   age = %d\n", ps->name, ps->age);
    11. }
    12. int main()
    13. {
    14.    struct Stu s = {"zhangsan", 20};
    15.    print(&s);//结构体地址传参
    16.    return 0;
    17. }

    3. 结构体传参

    1. struct B
    2. {
    3. char c;
    4. short s;
    5. double d;
    6. };
    7. struct Stu
    8. {
    9. //成员变量
    10. struct B sb;
    11. char name[20];//名字
    12. int age;//年龄
    13. char id[20];
    14. };
    15. void print1(struct Stu t)
    16. {
    17. printf("%c %d %lf %s %d %s\n", t.sb.c, t.sb.s,t.sb.d, t.name, t.age, t.id);
    18. }
    19. void print2(struct Stu* ps)
    20. {
    21. printf("%c %d %lf %s %d %s\n", ps->sb.c, ps->sb.s, ps->sb.d, ps->name, ps->age, ps->id);
    22. }
    23. int main()
    24. {
    25. //s是局部变量
    26. struct Stu s = { {'w',20,3.14},"张三",30,"202005034" };//对象 初始化
    27. //写一个函数打印S的内容
    28. print1(s); //传值调用 实参传递给形参 s创造一段空间,浪费空间和时间,t也需要创造一段相同空间,
    29. //对t的改变不会影响s,t只是对s的一份临时拷贝
    30. print2(&s); //传址调用 仅仅传递一个地址过去,只是传递一个指针大小空间,改变ps,s也会改变
    31. return 0;
    32. }
    直接上代码:
    1. struct S
    2. {
    3. int data[1000];
    4. int num;
    5. };
    6. struct S s = {{1,2,3,4}, 1000};
    7. //结构体传参
    8. void print1(struct S s)
    9. {
    10. printf("%d\n", s.num);
    11. }
    12. //结构体地址传参
    13. void print2(struct S* ps)
    14. {
    15. printf("%d\n", ps->num);
    16. }
    17. int main()
    18. {
    19. print1(s);  //传结构体
    20. print2(&s); //传地址
    21. return 0;
    22. }

    上面的 print1 print2 函数哪个好些?

    答案是:首选 print2 函数。
    原因:
    函数传参的时候,参数是需要压栈的。
    如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的
    下降。
    结论:
    结构体传参的时候,要传结构体的地址。

    1. int Add(int x, int y)
    2. {
    3. int z = 0;
    4. z = x + y;
    5. return z;
    6. }
    7. int main()
    8. {
    9. int a = 3;
    10. int b = 5;
    11. int c = 0;
    12. c = Add(a, b);//传参通常是从右往左传,先传b再传a
    13. return 0;
    14. }

    可以研究函数栈帧的创建和销毁 。

  • 相关阅读:
    笔记_Unity中的C#编程_112-116
    c# --- 泛型
    Windows Server 2016
    TCP和UDP C#代码实战
    Ubuntu 20.04 server永久关闭swap
    对接西部数据Western Digital EDI 系统
    2022软考高项十大领域知识整理(四)-人力资源管理、干系人管理、采购管理
    5月刚刚阿里面软件测试岗回来,3+1面任职阿里P7,年薪28*15薪
    opencv 通过滑动条调整阈值处理、边缘检测、轮廓检测、模糊、色调调整和对比度增强参数 并实时预览效果
    迅速了解JDK线程池以及Spring线程池
  • 原文地址:https://blog.csdn.net/m0_61741424/article/details/132711675