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

相关文章
|
30天前
|
存储 C语言
如何在 C 语言中实现结构体的深拷贝
在C语言中实现结构体的深拷贝,需要手动分配内存并逐个复制成员变量,确保新结构体与原结构体完全独立,避免浅拷贝导致的数据共享问题。具体方法包括使用 `malloc` 分配内存和 `memcpy` 或手动赋值。
42 10
|
29天前
|
存储 大数据 编译器
C语言:结构体对齐规则
C语言中,结构体对齐规则是指编译器为了提高数据访问效率,会根据成员变量的类型对结构体中的成员进行内存对齐。通常遵循编译器默认的对齐方式或使用特定的对齐指令来优化结构体布局,以减少内存浪费并提升性能。
|
1月前
|
编译器 C语言
共用体和结构体在 C 语言中的优先级是怎样的
在C语言中,共用体(union)和结构体(struct)的优先级相同,它们都是用户自定义的数据类型,用于组合不同类型的数据。但是,共用体中的所有成员共享同一段内存,而结构体中的成员各自占用独立的内存空间。
|
1月前
|
存储 C语言
C语言:结构体与共用体的区别
C语言中,结构体(struct)和共用体(union)都用于组合不同类型的数据,但使用方式不同。结构体为每个成员分配独立的内存空间,而共用体的所有成员共享同一段内存,节省空间但需谨慎使用。
|
1月前
|
编译器 C语言 C++
C语言结构体
C语言结构体
28 5
|
1月前
|
编译器 Linux C语言
C语言 之 结构体超详细总结
C语言 之 结构体超详细总结
21 0
|
1月前
|
存储 编译器 Linux
深入C语言:探索结构体的奥秘
深入C语言:探索结构体的奥秘
|
1月前
|
存储 编译器 C语言
c语言回顾-结构体(2)(下)
c语言回顾-结构体(2)(下)
31 0
|
1月前
|
存储 编译器 程序员
c语言回顾-结构体(2)(上)
c语言回顾-结构体(2)(上)
30 0
|
1月前
|
存储 C语言
c语言回顾-结构体
c语言回顾-结构体
17 0
下一篇
无影云桌面