C 语言中的结构体

2025年6月20日 | 阅读 10 分钟

在 C 语言编程中,结构体是一种用户定义的数据类型,它允许我们存储不同数据类型的集合。结构体的每个元素都称为成员。结构体可以模拟类和模板的使用,因为它可以存储各种信息。struct 关键字用于定义程序的结构。

语法

它具有以下语法:

在这个语法中,

  • structure_name:它表示结构体的名称。
  • data_type:它表示数据类型。
  • member1, member2:它表示成员名称。

让我们看一个为 C 语言中的实体雇员定义结构体的例子。

下图显示了在上述示例中定义的雇员结构体的内存分配。

c structure

为什么要使用 C 语言结构体?

C 语言编程中,有时我们需要存储一个实体的多个属性。实体不一定只包含一种类型的信息。它可以包含不同数据类型的不同属性。例如,一个实体 Student 可能有其姓名(字符串)、学号(整型)、分数(浮点型)。如果我们要存储有关学生实体这类信息,我们有以下方法:

  • 为存储姓名、学号和分数构建单独的数组。
  • 使用特殊数据结构存储不同数据类型的集合。

声明结构体变量

我们可以为结构体声明一个变量,以便我们可以轻松访问结构体的成员。有两种方法可以声明结构体变量:

  1. 在 main() 函数中使用 struct 关键字
  2. 在定义结构体时声明变量。

语法 1:在 main() 函数中定义结构体变量

语法 2:通过定义声明结构体变量

说明

在此示例中,结构体变量 var1 和 var2 在结构体定义后立即声明。这是一种在一步中指定和初始化结构体使用的简洁方法。

两种方法都是正确的,选择取决于程序的结构和可读性偏好。

访问结构体成员

有两种方法可以访问结构体成员:

  1. 使用 .(成员或点运算符)
  2. 使用 ->(结构体指针运算符)

使用点 (.) 运算符

在 C 语言编程中,点 (.) 运算符主要用于访问或修改结构体的数据成员。当我们直接在 C 语言中使用结构体变量时,它非常有用。

C 语言示例:使用点 (.) 运算符访问结构体成员

让我们看一个简单的例子,说明如何在 C 语言中使用点 (.) 运算符访问结构体成员。

示例

编译并运行

输出

employee 1 id : 101
employee 1 name : John

使用 ->(结构体指针运算符)

在 C 语言编程中,-> 运算符主要用于通过指向结构体的指针访问结构体的成员。如果有一个指向结构体的指针,我们不能直接使用点 (.) 运算符。相反,我们必须使用 -> 运算符,它一步完成解引用指针和访问成员的操作。

C 语言示例:使用 ->(结构体指针运算符)访问结构体成员

让我们看一个简单的例子,说明如何在 C 语言中使用结构体指针运算符访问结构体成员。

示例

编译并运行

输出

Employee ID: 201
Employee Name: Peter

基本结构体操作

C 语言中有几个基本的结构体操作。C 语言中一些主要的基本操作如下:

复制结构体

复制是 C 语言结构体最基本的操作之一。赋值运算符 (=) 可以用于将一个结构体变量赋值给另一个,就像它用于基本数据类型一样。

此操作创建浅拷贝,这意味着如果结构体包含指向动态生成内存的指针,则只复制指针值,而不是它们所引用的内存内容。如果我们要复制动态分配的数据,则必须通过分配新内存并传输内容来创建深拷贝。

C 语言示例:复制结构体

以下程序演示了 C 语言中复制结构体的基本示例。

示例

编译并运行

输出

Employee ID is: 1
Department is: D

说明

在此示例中,我们创建了一个结构体 `emp`,它包含两个成员:一个整数 `emp_Id` 和一个字符 `depart_ment`。在 `main()` 函数中,实例 `e1` 被初始化,然后使用赋值运算符复制到另一个实例 `e2`,这展示了浅拷贝。之后,打印存储在 `e2` 中的值,显示复制的员工 ID 和部门。

将结构体传递给函数

在 C 语言编程中,结构体可以作为值或引用(使用指针)传递给函数。当我们作为值传递时,会发送结构体的副本,函数内部的任何修改都不会影响原始数据。

如果我们要避免不必要的复制,尤其是在大型结构体中,传递指针会更有效,它允许直接访问和修改原始数据。

C 语言示例:将结构体传递给函数

让我们看一个示例,说明 C 语言中将结构体传递给函数的基本示例。

示例

编译并运行

输出

Product-1 Stock: 50
Product-2 Stock: 51

说明

在此示例中,我们定义了一个名为 `Product` 的结构体,它有一个名为 "st" 的整数元素,表示库存。`main` 函数初始化两个产品变量 `p1` 和 `p2`,然后将它们提供给 `Display` 函数(`p1` 按值传递,`p2` 按引用传递)。在函数内部,只有 `p2` 被永久修改。因此,结果显示 `p1` 保持 50 不变,`p2` 增加到 51。

将 typedef 与结构体一起使用

在 C 语言编程中,`typedef` 关键字允许为现有数据类型设置一个更短的别名。当与结构体一起使用时,它消除了在变量定义期间多次编写 `struct` 关键字的需要。它有助于提高代码可读性和可维护性,尤其是在大型程序中经常使用的结构体。

C 语言示例:将 Typedef 与结构体一起使用

让我们看一个示例,说明如何在 C 语言中将 typedef 与结构体一起使用。

示例

编译并运行

输出

Vehicle ID is: 11
Order Number is: 5

说明

在此示例中,我们使用 `typedef` 为两个单独的结构体生成别名 `Vehicle` 和 `Order`,每个结构体都有一个整数成员。在 `main` 函数中使用这些别名创建变量 `v` 和 `o` 并为其赋值。之后,`printf` 指令显示存储在相应结构体变量中的车辆 ID 和订单号。

结构体的大小

在 C 语言编程中,结构体的大小必须等于其各个成员的总和。然而,由于结构体填充,情况并非总是如此。填充是在成员之间插入额外字节以根据系统架构对齐内存中的数据的过程。这种对齐提高了访问效率并降低了数据检索期间使用的 CPU 周期。

在内存使用受限的情况下,使用结构体打包来避免填充。C 语言有两种典型的紧密打包结构体的方法:

  • 使用 `#pragma pack (1)`
  • 使用 `__attribute__(packed)`

C 语言示例:结构体的大小

让我们看一个示例,说明 C 语言中结构体的大小。

示例

编译并运行

输出

The size of the PackedItem is: 9 bytes
The size of the RegularItem is: 9 bytes

说明

在此示例中,我们使用了两个结构体:`Packed_Item`,它使用 `#pragma pack(1)` 禁用填充,以及 `Regular_Item`,它使用默认填充。两者都包含一个字符、一个整数和一个浮点数,但它们的输出大小均为 9 字节,这表明编译器强制了紧密对齐或者优化设置抑制了填充。

嵌套结构体

在 C 语言编程中,嵌套结构体是一个强大的概念,它将一个结构体与另一个结构体组合在一起。这种方法能够建模复杂的、分层的数据,其中关联的子组以单个更大的框架进行结构化。它提高了代码可读性,保持数据逻辑有序,并支持模块化开发。结构体嵌套主要有两种技术:

  • 嵌入式结构体

嵌入式结构体是 C 语言中的一种嵌套结构体,其内部结构体直接在外部(父)结构体内声明。它特定于该结构体,不能在其他地方使用。

C 语言嵌入式结构体示例

  • 独立结构体

独立结构体是一种嵌套结构体,其中内部结构体独立声明,随后被合并到外部结构体中。它允许内部结构体在各种结构体中使用。

独立结构体示例

访问嵌套结构体成员

当一个结构体嵌套在另一个结构体中时,我们可以重复使用点 (.) 运算符来访问内部(子)结构体的成员。它允许我们以整洁和逻辑的方式从深度嵌套的数据中提取和修改值。

访问嵌套结构体成员示例

让我们看一个示例,说明如何在 C 语言中访问嵌套结构体成员。

示例

编译并运行

输出

Employee ID is: 1
Employee Name is: Peter
Department ID is: 13
Department Name is: Computer science

说明

在此示例中,我们使用了两个结构体 `Dept` 和 `Emp`。在 `main()` 函数中,`Emp` 变量用员工和部门信息初始化,并使用点运算符访问嵌套成员。

自引用结构体

自引用结构体是指在其成员中包含指向自身类型的指针的结构体。它允许结构体引用或链接到同一类型的实例,这在创建链表、树和图等链式数据结构时非常有用。

这些结构体对于动态内存分配是必要的,并且常用于高级算法和数据结构。

C 语言自引用结构体示例

让我们看一个示例,说明 C 语言中的自引用结构体。

示例

编译并运行

输出

Node-1 Data is: 10
Node-2 Data is: 20

说明

在此示例中,我们定义了一个自引用 `Node` 结构体,其中每个节点包含数据 (d) 和指向下一个节点的指针 (next)。它创建两个节点,将它们连接起来,然后使用 `next` 指针输出两个节点的数据。

结构体的用途

C 语言中结构体的几种用法如下:

  • 在 C 语言中创建自定义数据类型,包括本地不支持的日期、时间、复数等。
  • 将相似信息组织成一个单元,以便于访问和管理。
  • 创建复杂的`数据结构`,如链表、树和图。
  • 为了从函数返回多个值,将不同的数据类型封装在一个结构体中。

C 语言结构体 MCQ

1. 在 C 语言中,哪个关键字用于定义结构体?

  1. struct
  2. structure
  3. record
  4. class

答案: a) struct


2. 通过结构体变量访问结构体成员的语法是什么?

  1. 使用 -> 运算符
  2. 使用 . 运算符
  3. 使用 :: 运算符
  4. 使用 , 运算符

答案: b) 使用 . 运算符。


3. 使用指针访问结构体成员时使用哪个运算符?

  1. .
  2. *
  3. &
  4. ->

答案: d) ->


4. C 语言中空结构体的大小是多少(假设是标准 C)?

  1. 0
  2. 1
  3. 编译器决定
  4. 不允许

答案: c) 编译器决定


5. C 语言中结构体可以包含另一个结构体吗?

  1. 可以
  2. 不可以
  3. 只能与 typedef 一起使用
  4. 只能是指针

答案: a) 可以


下一个主题C 语言中的 typedef