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

相关文章
|
9天前
|
程序员 C语言
【C语言】初步认识结构体
【C语言】初步认识结构体
12 0
|
25天前
|
C语言
C语言结构体内存对齐
C语言结构体内存对齐
|
4天前
|
存储 算法 程序员
【C言专栏】C 语言结构体的应用与实践
【4月更文挑战第30天】C语言中的结构体是自定义数据类型的关键,它组合不同类型的數據以创建新类型,尤其适合处理复杂对象如学生信息。通过定义结构体如`struct Student`,包含名字、学号和成绩,可以方便地实例化和访问成员。结构体在链表实现、函数参数传递和数组中都有广泛应用,如表示链表节点和处理批量数据。理解并熟练运用结构体对于C语言编程至关重要,能提升代码效率和可读性。
|
7天前
|
C语言
【C生万物】C语言分支和循环语句
【C生万物】C语言分支和循环语句
|
10天前
|
编译器 Linux C语言
C语言:结构体(自定义类型)知识点(包括结构体内存对齐的热门知识点)
C语言:结构体(自定义类型)知识点(包括结构体内存对齐的热门知识点)
|
11天前
|
存储 C语言
C语言中定义结构体类型变量的深入探索
C语言中定义结构体类型变量的深入探索
8 0
|
19天前
|
存储 C语言
结构体(C语言)
结构体(C语言)
|
25天前
|
存储 C语言
C语言自定义类型结构体详解
在C语言中,结构体是复合数据类型,能组合不同类型的数据显示。定义结构体用`struct`关键字,如`struct Student {char name[20]; int age; float score;};`。声明结构体变量如`struct Student stu1;`,访问成员用`.`操作符,如`stu1.age = 20;`。初始化可直接赋值`struct Student stu1 = {"李四", 22, 85.5};`。结构体数组如`struct Student stuArray[3]`,结构体指针如`struct Student *pStu = &stu1;`。
7 0
|
26天前
|
存储 安全 网络协议
自定义类型-结构体,联合体和枚举-C语言
自定义类型-结构体,联合体和枚举-C语言
|
28天前
|
存储 搜索推荐 编译器
【C语言】一篇文章深入解析联合体和枚举且和结构体的区别
【C语言】一篇文章深入解析联合体和枚举且和结构体的区别