当前位置:   article > 正文

C语言--结构体基本用法_c语言结构体使用

c语言结构体使用

前言:

        本章让我们初步认识和使用结构体,但不会深入解读。

为什么要有结构体?

        因为在实际问题中,一组数据往往有很多种不同的数据类型。例如,登记学生的信息,可能需要用到 char型的姓名,int型或 char型的学号,int型的年龄,char型的性别,float型的成绩。又例如,对于记录一本书,需要 char型的书名,char型的作者名,float型的价格。在这些情况下,使用简单的基本数据类型甚至是数组都是很困难的。而结构体,则可以有效的解决这个问题。
        结构体本质上还是一种数据类型,但它可以包括若干个“成员”,每个成员的类型可以相同也可以不同,也可以是基本数据类型或者又是一个构造类型。

1. 结构体的声明

1.1 结构的基础知识

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

 1.2 结构的声明

  1. struct tag//声明结构体,struct+名
  2. {
  3. member-list;//成员变量列表
  4. }variable-list;//变量列表

        变量列表稍后再做解释。 

例如描述一个学生:
  1. #include<stdio.h>
  2. struct Stu
  3. {
  4. char name[20];//名字
  5. int age;//年龄
  6. char sex[5];//性别
  7. char id[20];//学号
  8. }s3,s4;//分号不能丢
  9. //s3,s4是全局变量
  10. int main()
  11. {
  12. struct stu s1;
  13. struct stu s1;
  14. //struct不能省略
  15. //s1,s2是结构体的变量,是局部变量
  16. return 0;
  17. }

每次定义局部变量都要加上struct,有没有办法省略掉呢?

来看下这种写法:

  1. #include<stdio.h>
  2. typedef struct Stu
  3. {
  4. char name[20];//名字
  5. int age;//年龄
  6. char sex[5];//性别
  7. char id[20];//学号
  8. }stu;stu是重命名产生的新的类型
  9. int main()
  10. {
  11. stu s1;
  12. stu s2;
  13. //这里就可以省略struct了
  14. return 0;
  15. }

        在上面的写法,我们在声明时加上了typedef,对结构体进行了重命名,这样就能在定义局部变量时省略struct关键字了。

1.3 结构成员的类型

结构的成员可以是标量、数组、指针,甚至是其他结构体。
  1. struct B
  2. {
  3. int a;
  4. char b;
  5. };
  6. struct A
  7. {
  8. char c;
  9. int num;
  10. int arr[10];
  11. double* pd;
  12. struct B sb;
  13. struct B* pd;
  14. };

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

有了结构体类型,那如何定义变量,其实很简单。
  1. struct Point
  2. {
  3. int x;
  4. int y;
  5. }p1; //声明类型的同时定义变量p1
  6. struct Point p2; //定义结构体变量p2(全局)
  7. struct Point p3 = {x, y};//初始化:定义变量的同时赋初值。
  8. struct Stu        //类型声明
  9. {
  10. char name[15];//名字
  11. int age;      //年龄
  12. };
  13. struct Stu s = {"zhangsan", 20};//初始化
  14. struct Node
  15. {
  16. int data;
  17. int age
  18. struct Point p;
  19. struct Node* next;
  20. }n1 = {10, 20, {4,5}, NULL}; //结构体嵌套初始化(结构体内包含结构体)
  21. int main()
  22. {
  23. //按照顺序初始化
  24. struct Node n2 = {10,20, {5, 6}, NULL};//结构体嵌套初始化
  25. //指定成员初始化
  26. struct Node n3={.data = 1000,.age = 20};
  27. return 0;
  28. }

总结:结构体的初始化可以按照顺序初始化,也可以指定成员初始化。

 2. 结构体成员的访问

结构体访问有两种方式:
        1.结构体变量 . 成员名
        2.结构体指针->成员名

 1.结构体变量 . 成员名方式:

  1. #include<stdio.h>
  2. #include<string.h>
  3. struct stu
  4. {
  5. char name[20];
  6. int age;
  7. };
  8. void set_s(struct stu t)
  9. {
  10. t.age = 18;
  11. //t.name = "zhangsan";//这种写法在这里行不通,因为name是数组名,数组名是常量的地址
  12. strcpy(t.name, "zhangsan");//可以使用字符串拷贝函数解决
  13. }
  14. int main()
  15. {
  16. struct stu s = {0};
  17. //写一个函数给函数s存放数据
  18. set_s(s);
  19. return 0;
  20. }

从结果看结构体变量s,并未被赋值,这是为什么呢?

 所以我们应该要传递过去。

  1. #include<stdio.h>
  2. #include<string.h>
  3. struct stu
  4. {
  5. char name[20];
  6. int age;
  7. };
  8. void set_s(struct stu* ps)
  9. {
  10. (*ps).age = 18;
  11. //t.name = "zhangsan";//这种写法在这里行不通,因为name是数组名,数组名是常量的地址
  12. strcpy((*ps).name, "zhangsan");//可以使用字符串拷贝函数解决
  13. }
  14. int main()
  15. {
  16. struct stu s = {0};
  17. //写一个函数给函数s存放数据
  18. set_s(&s);
  19. return 0;
  20. }

 此时s内就有值了

 2.结构体指针->成员名方式:

对于上面指针的方式,我们就可以使用->了

  1. #include<stdio.h>
  2. #include<string.h>
  3. struct stu
  4. {
  5. char name[20];
  6. int age;
  7. };
  8. void set_s(struct stu* ps)
  9. {
  10. ps->age = 18;
  11. //t.name = "zhangsan";//这种写法在这里行不通,因为name是数组名,数组名是常量的地址
  12. strcpy(ps->name, "zhangsan");//可以使用字符串拷贝函数解决
  13. }
  14. int main()
  15. {
  16. struct stu s = {0};
  17. //写一个函数给函数s存放数据
  18. set_s(&s);
  19. return 0;
  20. }

 结果相同。

但如果只是打印的话就不需要传地址,只需要变量临时拷贝就行了

3. 结构体传参 

 直接上代码:

  1. struct S {
  2. int data[1000];
  3. int num;
  4. };
  5. struct S s = {{1,2,3,4}, 1000};
  6. //结构体传参
  7. void print1(struct S s)
  8. {
  9. printf("%d\n", s.num);
  10. }
  11. //结构体地址传参
  12. void print2(struct S* ps)
  13. {
  14. printf("%d\n", ps->num);
  15. }
  16. int main()
  17. {
  18. print1(s); //传结构体
  19. print2(&s); //传地址
  20. return 0;
  21. }

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

答案是:首选print2函数。

原因:

函数传参的时候,参数是需要压栈的。

如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。

结论:

结构体传参的时候,要传结构体的地址。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/426267
推荐阅读
相关标签
  

闽ICP备14008679号