南哪 2022-7-data-types
data-types 中提到了一些更进阶的数据类型定义方式,在这里某 CQ 将一些内容重述,以便于更好地理解。
struct
C 语言不是一种面向对象语言,因此,它没有对象的概念,但是结构体如果用的好的话,也能够媲美对象。
struct
结构体是一种复合类型,它将多个不同类型的变量组合在一起,形成一个整体。
struct
类型的变量在定义时,会分配一段连续的内存空间,其中包含内部所有字段的空间。
在具体使用的时候,你需要先定义结构体类型及其成员,向编译器告知,你创建了这样一个类型,然后才可以使用这个类型来定义变量:
// 定义结构体类型
struct Data {
int data1;
char data2;
double data3;
};
// 定义结构体变量
struct Data data;
// 使用结构体变量
data.data1 = 1;
data.data2 = 'a';
data.data3 = 3.14;
使用 struct
可以很方便的将多个数据打包,使得程序更加的通俗易懂。
提示
你也可以不给结构体名字,它将作为匿名结构体,你没法再在别处使用它,你只能在创建的时候立刻使用它:
struct {
int data1;
char data2;
double data3;
} data;
data.data1 = 1;
// ...
提示
使用之前提到过的 typedef
,你可以将 struct
类型重命名,这样在定义变量时,就不需要写 struct
关键字了:
你可以在
typedef
定义的别名中加上_t
后缀,表示这是typedef
定义的类型
typedef struct Data data_t;
struct Data {
// ...
}
data_t data;
// ...
接下来,关键的来了,我们知道 C++ 中的结构体中是可以定义方法的,那么 C 语言中有没有办法实现类似的功能呢?
有的,兄弟,有的,我们可以使用函数指针来申明一些结构体成员,在创建结构体变量实例时,我们可以将函数赋值给这些成员,这样就可以实现类似的方法功能了:
比如,我们创建一个 utils_t
类型,来存放一些工具函数:
typedef utils utils_t
// 因为只是定义,所以函数参数部分,你可以不写变量名,实现的时候还是要写的
struct utils {
void (*swap) (int *, int *);
int (*max) (int, int);
int (*min) (int, int);
}
// 实现这些函数
// 为避免重名,你最好加上前缀
void utils_swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
int utils_max(int a, int b) {
return a > b ? a : b;
}
int utils_min(int a, int b) {
return a < b ? a : b;
}
// 在使用时,动态创建 `utils_t` 实例,在使用过后也指定销毁方法
// 这样看上去麻烦,但反而更有利于代码的管理
// 比如说你需要在创建时初始化一些字段值,在销毁时做一些清理工作,这样写就会很好改动。
utils_t *create_utils() {
utils_t *this = malloc(sizeof(utils_t));
this->swap = utils_swap;
this->max = utils_max;
this->min = utils_min;
return this;
}
void destroy_utils(utils_t *this) {
free(this);
}
提示
上面定义的方法都相当于是静态方法,这些方法不会与实例进行交互,如果一些方法涉及到与结构体实例发生交互,你只能通过传入实例来实现,像这样:
typedef struct Dog dog_t
struct Dog {
int age;
void (*grow) (dog_t *);
}
// 使用 `this`,让含义更贴近面向对象表达
void dog_grow(dog_t* this) {
this->age += 1;
}
// ...
// 使用
dog.grow(&dog);
union
union
联合体,与 struct
结构体类似,但是它只能存放一种数据类型,而且所有字段共享同一块内存空间,因此,联合体的大小等于其中最大的字段的大小。
联合体通常用于存储一些互斥的数据,比如,一个变量,它可能是整数,也可能是浮点数,也可能是字符,那么就可以使用联合体来存储,这样在存储时,只需要分配一块内存空间即可。
union Data {
int data1;
char data2;
double data3;
};
union Data data;
data.data1 = 1; // 此时,data2 和 data3 的值将不可预测
data.data2 = 'a'; // 此时,data1 和 data3 的值将不可预测
data.data3 = 3.14; // 此时,data1 和 data2 的值将不可预测
union
只是一种辅助手段,如果滥用,他只会严重破坏代码的可读性。你只应当在清楚自己到底在做什么的时候使用它。
题单链接:
南哪2022-7-data-types - 题单 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这次只有三道题