跳转到内容

C 编程/高级数据类型

来自维基教科书,开放的书本,开放的世界
Clipboard

待办事项
添加关于递归和循环相互包含数据结构的信息和部分。


上一节: 开始练习 C 编程 下一节: 指针和数组

变量 这一章中,我们了解了基本数据类型。然而,高级数据类型让我们在程序中管理数据时更加灵活。

结构体

[编辑 | 编辑源代码]

结构体是由其他数据类型(可能包括其他结构体)的变量组成的。它们用于将信息片段分组到有意义的单元中,并且还允许一些其他情况下不可能的构造。在结构体中声明的变量称为“成员”。使用struct关键字定义结构体。例如

struct mystruct {
    int int_member;
    double double_member;
    char string_member[25];
} struct_var;

struct_var 是类型为 struct mystruct 的变量,我们是在定义新的 struct mystruct 数据类型时一起声明的。更常见的是,在定义结构体之后,使用以下形式声明结构体变量

struct mystruct struct_var;

通常的做法是创建一个类型别名,这样我们就不必一直输入 "struct mystruct"。C 允许我们使用typedef语句做到这一点,该语句为类型创建别名

typedef struct {
    // ...
} Mystruct;

struct 本身是一个不完整的类型(因为第一行没有名称),但它被别名为 Mystruct。然后可以这样使用

Mystruct struct_var;

可以使用成员访问运算符 .(点)或间接成员访问运算符 ->(箭头)访问结构体变量的成员,如果结构体变量是指针的话

struct_var.int_member = 0;
struct_var->int_number = 0; // this statement is equivalent to: (*struct_var).int_number = 0;

(指针将在下一章中解释。)结构体不仅可以包含自己的变量,还可以包含指向其他结构体的变量。这允许递归定义,当与指针一起使用时非常强大

struct restaurant_order {
    char description[100];
    double price;
    struct restaurant_order *next_order;
};

这是 链表 数据结构的实现。每个节点(一个餐厅订单)都指向另一个节点。链表在最后一个节点(在我们的示例中,这将是最后一个订单)终止,最后一个节点的 next_order 变量将被分配为 NULL

当与typedef一起使用时,递归结构体定义可能会很棘手。无法使用其别名定义在自己的类型中声明结构体变量,因为typedef语句在评估之前,别名定义不存在

typedef struct Mystruct {
    // ...
    struct Mystruct *pointer; // Mystruct *pointer; would cause a compile-time error
} Mystruct;

结构体类型的尺寸至少是其所有成员尺寸的总和。但是,编译器可以自由地在结构体成员之间插入填充字节,以使成员对齐到某些约束。例如,在许多 32 位架构上,包含字符和浮点数的结构体将占用 8 个字节。

联合体

[编辑 | 编辑源代码]

联合体的定义类似于结构体。两者之间的区别在于,在结构体中,成员占据内存的不同区域,但在联合体中,成员占据内存的同一区域。因此,在以下类型中,例如

union {
    int i;
    double d;
} u;

程序员可以访问 u.iu.d,但不能同时访问两者。由于 u.iu.d 占据内存的同一区域,修改一个会修改另一个的值,有时会以不可预测的方式。这也是联合体在实践中很少见的主要原因。

联合体的尺寸与其最大成员的尺寸相同。

枚举类型

[编辑 | 编辑源代码]

枚举类型是人工数据类型,表示标签和整数之间的关联。与结构体或联合体不同,它们不包含其他数据类型。一个示例声明

enum color {
    red,
    orange,
    yellow,
    green,
    cyan,
    blue,
    purple,
} crayon_color;

在上面的示例中,red 等于 0,orange 等于 1,... 等等。可以为标签分配整数范围内的值,但它们必须是文字。

与结构体和联合体类似的声明语法也适用于枚举类型。此外,通常情况下,无需关心标签表示的整数

enum weather weather_outside = rain;

这种特殊的属性使枚举类型在 switch-case 语句中特别方便

enum weather {
    sunny,
    windy,
    cloudy,
    rain,
} weather_outside;

// ...

switch (weather_outside) {
case sunny:
    wear_sunglasses();
    break;
case windy:
    wear_windbreaker();
    break;
case cloudy:
    get_umbrella();
    break;
case rain:
    get_umbrella();
    wear_raincoat();
    break;
}

枚举类型是一种简化的方式,用于在 C 中模拟关联数组。

上一节: 开始练习 C 编程 下一节: 指针和数组
华夏公益教科书