C生万物 | 万字细说C语言结构体-1

简介: C生万物 | 万字细说C语言结构体

一、结构体的声明

1、结构的基础知识

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

2、结构的声明

下面是结构体声明的形式

struct tag
{
  member-list;
}variable-list;

例如现在要使用结构体来描述一个学生:里面就存放了一个学生所具有的基本信息,如姓名、年龄、性别、身高

struct Stu {
  char name[20];  //姓名
  int age;    //年龄
  char sex[2];  //性别
  float height; //身高
};  

或者用结构体来描述一本书,里面存放了:书名、作者、定价、书号

struct Book {
  char name[20];
  char author[20];
  double price;
  int id;
};

==不仅如此,结构的成员还可以是标量、数组、指针,甚至是其他结构体==

3、特殊的声明

接下去我来介绍一种特殊的结构体声明形式,也就是【匿名结构体】,什么是匿名结构体呢?也就是没有结构体名称

//匿名结构体类型
struct
{
  int a;
  char b;
  float c;
}x;
struct
{
  int a;
  char b;
  float c;
}a[20], * p;
  • 可以看到,我故意将两个结构体的内容设置成一样,然后直接在声明的时候就定义出了它们各自的结构体成员,第二个结构体定义了一个结构体数组和结构体指针
  • 此处我使用这个结构体指针去接收第一个结构体定义出来的变量x,此时你应该会觉得合情合理,但是编译之后却看到【它们的类型不兼容】,这是为什么呢?
p = &x;

image.png

原因其实就在于这个【匿名结构体】

  • 对于匿名结构体来说呢只能在声明的时候用一次,后面就不能再用了。所以这个东西其实也没什么用,了解一下就行
  • 不过这个语法形式和C++中的【匿名对象】很类似,声明周期只在当前行,进入下一行就会调用析构函数

4、结构的自引用

有关结构体自引用这块,就要说到数据结构里面的相关知识了,可能有的读者没听过,这也没关系,准备发车🚗

  • 说起自引用这一块最典型的其实就是数据结构中的《链表》,可能有的C语言教科书上也会提及。但如果要说链表的话那就得先说说顺序表
  • 对于顺序表而言,就是存放在内存中一块连续的存储空间,具体可以看看 数据结构体之循序表
  • 对于链表而言,是由存放在内存中一些不连续结点所链接而成的,,具体可以看看 数据结构体之链表image.png
  • 那要如何去声明一个链表的结构体,下面这样可行吗?
struct Node
{
  int data;
  struct Node next;
};
  • 可以看到,程序报出了错误,说是【struct Node未定义】,这是为什么呢?

image.png

  • 其实对于链表的单个结点来说,是由两个域组成的,一个叫做【数据域】,是存放结点数据的,一个叫做【指针域】,是存放下一个结点在堆内存中地址,图示如下:
  • 这里讲的不是很清楚,了解一下即可,有兴趣的同学可以去看看上面那篇链表的文章

image.png

  • 那指针域要存放一个结点,也就是结构体的地址,就必须要一个结构体指针,此时我们就可以将代码写成下面这样,每个结构体指针都指向下一个结点的地址
struct Node
{
  int data;
  struct Node* next;
};
  • 此时就可以通过这个结构体定义出有关链表的结点,然后去初始化链接每个结点即可
struct Node list;

但你是否有觉得上面这种形式太麻烦了,每次在定义一个结构体变量的时候都要在前面加上一个struct,如果可以不加该多好

  • 这个其实很好办,只需要在结构体声明的时候在前面加上要一个typedef关键字即可,然后再定义变量的位置为其重命名一下,那在定义结构体变量的时候就不需要再加上struct关键字了
typedef struct Node
{
  int data;
  struct Node* next;
}Node;
Node list;

【友情提示】:可不能把结构体定义成下面这样,Node* next;这种写法是错误的,因为到这行为止,结构体还不认识Node,所以是不可以使用它的

typedef struct Node
{
  int data;
  Node* next;
}Node;

image.png

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

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

  • 第一种方法就是直接在声明出结构体的时候就可以定义结构体变量,例如这里的s1、s2、s3指的的都是一个学生,而且它们属于全局变量
struct Stu {
  char name[20];  //姓名
  int age;    //年龄
  char sex[2];  //性别
  float height; //身高
}s1, s2, s3;  //全局变量
  • 第二种方法就是脱离结构体进行定义,不过这和我们在定义普通变量的格式是一样的,也要在前面加上数据类型,比如int a前面的int
  • struct Stu就是这个结构体的类型,不要忘记加上前面的struct这个修饰符了。下面的【ss】定义在外面,那就是全局变量;【su】定义在函数内部,那就是局部变量
struct Stu ss;    //全局变量
int main(void)
{
  struct Stu su;  //局部变量
  return 0;
}
  • 如果你觉得每次写 struct Stu太麻烦了,也是有办法了,那就是为其进行一个重命名,一般我们直接在结构体最前面加上一个typedef关键字,然后在定义处为其做一个重命名
typedef struct Stu {
  char name[20];  //姓名
  int age;    //年龄
  char sex[2];  //性别
  float height; //身高
}S;   

因此可以说 S == struct Stu,定义方式就简洁了许多

struct Stu su;
S su2;

接下去来讲讲结构体如何初始化

  • 我们将初始化的内容使用花括号{ }括起来,里面就可以对结构体的成员进行一个初始化,分别意义对照进行初始化即可
struct Stu su = { "zhangsan", 20, "男", 180 };
  • 这里我又定义了一个【点】的结构体,成员变量即为坐标x和坐标y
struct Point {
  int x;
  int y;
};
  • 对其初始化也很简单,如下
struct Point p = { 10, 20 };

但是现在我又有了一个结构体,这个结构体内部呢又有一个结构体,就是上面这个【点】,这该如何初始化呢?

struct MyStruct
{
  char c;
  struct Point p;
  double d;
  char str[20];
};
  • 很简单,其他普通的成员变量就正常初始化,结构体成员变量的话也按照结构体的方式使用花括号括起来即可
struct MyStruct ms = { 'c', {40, 80}, 3.14f, "haha" };

来看看初始化后的结果

image.png

  • 那有同学问了,若是我不想按照顺序来进行初始化呢?可以吗?答案是可以的
  • 只需要用[.]操作符然后选择对应的成员变量进行初始化即可
struct MyStruct ms2 = {.d = 6.28, .str = "abcdef", .c = 'cc'};    //乱序初始化

来看看这样初始化后的结果为多少。可以观察到没有被初始化到的变量就取为默认值,也就是这个【点】

image.png

相关文章
|
6天前
|
算法 Java 程序员
面向对象编程(OOP)通过对象组合构建软件,C语言虽是过程式语言,但可通过结构体、函数指针模拟OOP特性
【6月更文挑战第15天】面向对象编程(OOP)通过对象组合构建软件,C语言虽是过程式语言,但可通过结构体、函数指针模拟OOP特性。封装可使用结构体封装数据和方法,如模拟矩形对象。继承则通过结构体嵌套实现静态继承。多态可通过函数指针模拟,但C不支持虚函数表,实现复杂。C语言能体现OOP思想,但不如C++、Java等语言原生支持。
26 7
|
7天前
|
编译器 C语言
【C语言基础】:自定义类型(一)--> 结构体-2
【C语言基础】:自定义类型(一)--> 结构体
|
7天前
|
编译器 Linux C语言
【C语言基础】:自定义类型(一)--> 结构体-1
【C语言基础】:自定义类型(一)--> 结构体
|
15天前
|
C语言
C语言学习记录——枚举(定义、与结构体的区别、优点)
C语言学习记录——枚举(定义、与结构体的区别、优点)
16 3
|
15天前
|
存储 编译器 C语言
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)一
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)一
21 2
|
15天前
|
编译器 Linux C语言
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)二
C语言学习记录——结构体(声明、初始化、自引用、内存对齐、结构体设计、修改默认对齐数、结构体传参)二
18 1
|
16天前
|
编译器 C语言
C语言深度理解之——结构体内存对齐
C语言深度理解之——结构体内存对齐
14 1
|
18天前
|
C语言
【初始C语言8】详细讲解初阶结构体的知识
【初始C语言8】详细讲解初阶结构体的知识
|
7天前
|
C语言
C语言——结构体
C语言——结构体
5 0
|
16天前
|
C语言
C语言结构体教程:从入门到实践(保姆式教学)
C语言结构体教程:从入门到实践(保姆式教学)
13 0