> 文档中心 > C语言自学之路十四(详解C语言初阶结构体)

C语言自学之路十四(详解C语言初阶结构体)


本文所结合图书及视频

《C语言程序设计(第四版)谭浩强.pdf》
《C语言入门到精通—鹏哥带你C语言入门到精通》
《郝斌老师的C语言自学视频》
这些在B站上都能找得到的。

学习目标:

对C语言的结构体有个全面的了解,会使用简单的结构体。

章节内容:

   1.结构体类型的声明
   2. 结构体初始化
   3. 结构体成员访问
   4. 结构体传参

一 、结构体类型的声明

1、结构体基础知识
  结构是一些值的 [集合],这些值被称为成员变量。结构的每个成员可以是不同类型的变量。说到集合,我们之前学习过的数组也是一种相同类型元素的集合,但是结构体的值的类型可以是不同的。
  C语言结构体(Struct)从本质上讲是一种自定义的数据类型,只不过这种数据类型比较复杂,是由 int、char、float 等多种基本类型组成的。所以说结构体是一种复合类型。

2、结构体的声明
  在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据。结构体的定义形式为:

struct 结构体名字{结构体所包含的成员变量};

举例: 比如我们要定义一个有关学生的结构体,可以按照下面的方法写:

struct Stu{char name[20];  // 名字char sex[5];   // 性别int age;    // 年龄char id[20]; //  学号}s1,s2;   // s1和s2也是结构体变量,不过是全局变量int main(){struct Stu s; // 用struct Stu类型创建了一个s对象return 0; //  s是局部变量// }

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

二、结构体初始化

  和其他类型变量一样,对结构体变量也可以在定义时指定初始值。

struct Stu {char name[15]; // 名字int age;     // 年龄};struct Stu s = {"zhangsan", 25}; //定义变量同时赋初值

  还有结构体嵌套初始化

struct point{int x;int y;};struct Node{int data;struct point p;//成员变量也是结构体struct Node* next; //结构体指针变量}n1 = {10,{4, 5}, NULL};//结构体嵌套初始化struct Node 2 = {20, {5, 6}, NULL}; //结构体嵌套初始化

注意:
  当结构体成员变量中有结构体类型时,初始化时要将其单独用{ }括起来!

三、结构体成员的访问

  结构体成员访问有两个操作符,就是. -> 操作符,我们在操作符那章C语言 操作符详解二也讲过了,大家如果忘记了,也可以翻过去重新复习下!具体用法我们再举例说明下。

struct xiaoming{char c;short s;double d;};struct Stu{struct xiaoming;  char name[20];  //姓名char sex[5];   // 性别int age;    // 年龄char id[20]; //  学号}s1,s2;   // s1和s2也是结构体变量,不过是全局变量int main(){struct Stu s = { {'w', 20, 5.2113}, "张三", 30, "D20220715"}; //假设我们要将 w 打印出来,我们可以这样写printf("%c\n", s.xiaoming.c); //因为 w 是在结构体 s 中成员变量结构体xiaoming的成员变量中,// s为首层,xiaoming为第二层,所以要用两个点访问。//假设我们要将 “张三” 打印出来,我们可以这样写printf("%s\n", s.name);//因为 “张三” 是结构体 s 中的成员,一个点就可以访问到。return 0; //  s是局部变量

  以上是.结构体成员访问操作符的用法,那么我们说还有->结构体成员访问操作符,它其实主要用在结构体指针变量中。

struct xiaoming{char c;short s;double d;};struct Stu{struct xiaoming;  char name[20];  //姓名char sex[5];   // 性别int age;    // 年龄char id[20]; //  学号}s1,s2;   // s1和s2也是结构体变量,不过是全局变量int main(){struct Stu s = { {'w', 20, 5.2113}, "张三", 30, "D20220715"}; struct Stu * pa = &s;  // pa指向的是一个结构体类型的类型//假设我们要将 w 打印出来,我们可以这样写printf("%c\n", (*pa).xiaoming.c); //pa指向s 将pa解引用等于s *pa = s printf("%c\n",pa->xiaoming.c);  //pa指向s 可直接用->访问到,但是xiaoming不是结构体指针,所以还是要写xiaoming.c//假设我们要将 “张三” 打印出来,我们可以这样写printf("%s\n", s.name);//因为 “张三” 是结构体 s 中的成员,一个点就可以访问到。printf("%s\n", pa->name); // pa指向s 可直接用->访问。 return 0; //  s是局部变量

   -> 操作符主要是用在结构体指针中,且在结构体指针中我们一般用->操作符,而很少使用解引用的操作。

四、结构体传参

  当结构体作为函数参数来使用时,有两种方法,一种是按值传递,一种是按址传递。结构体变量名代表的是整个集合本身,作为函数参数时传递的是整个集合,也就是所有成员。

struct xiaoming{char c;short s;double d;};struct Stu{struct xiaoming;  char name[20];  //姓名char sex[5];   // 性别int age;    // 年龄char id[20]; //  学号};void printf1(struct Stu t){printf("%c %d %lf %s %d %s\n", t.xiaoming.c,t.xiaoming.s,t.xiaoming.d,t.name,t.age,t.id);}void printf2(struct Stu *pa){printf("%c %d %lf %s %d %s\n", pa->xiaoming.c,pa->xiaoming.s,pa->xiaoming.d,pa->name,pa->age,pa->id);}int main(){struct Stu s = { {'w', 20, 5.2113}, "张三", 30, "D20220715"}; //用函数打印 s 的内容printf1(s); // 打印结果 w 20 5.211300 张三 30 D20220715printf2(s); // 打印结果 w 20 5.211300 张三 30 D20220715//虽然 printf1 和 printf2 打印的结果一样,但是更推荐用printf2这种方法,其所占空间更少,速度更快,效率更高!return 0;

  如果结构体成员较多,尤其是成员为数组时,传送的时间与空间开销都会很大,影响程序的运行效率。所以最好的办法就是使用结构体指针,这时由实参传向形参的只是一个地址,会大大降低程序运行的空间与提高运行速度!
注意事项:
   按值调用:形参是实参的临时拷贝,空间等同,改变形参的值不会改变实参的值。
   按址调用:形参接受的只是实参的地址,空间很小,改变形参的值能改变实参的值,时间空间开销更小,效率更高!

  本节的内容就分享到这里了,关于更高级的结构体内容我会放在后期的章节来重点讲解,下期我们一起学习在编写程序时的一些调试技巧
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述