优雅地使用#include / 2022-01-05

#include并不只是用来引用头文件的,合理的使用#include可以让代码更优雅。

通常我们都是使用#include包含头文件,如下:

#include <stdio.h>

理解下#include的作用就是在预编译阶段将指定的文件原样拷贝到引用的地方。实际上还可以使用#include优雅的处理一些逻辑。

引用代码块

假设有一个C文件,里面包含不同的代码块。我们希望通过宏开关的方式控制不同代码块的打开关闭,但我们又不想将这些代码块都写在这个C文件中(可能导致C文件很长)。此时,就可以通过将代码块拆分到不同的文件中,并通过#include的方式引用。如下:

#ifdef EASEAPI_COM_BLOCK_A
#include "A.inc"
#endif

#ifdef EASEAPI_COM_BLOCK_B
#include "B.inc"
#endif

这里的A.inc和B.inc都是普通的C文件,这里只所以命名为inc后缀,是为了隐式地表明它不是一个普通的C文件:在A.inc被#include后,就不能直接把A.inc添加到源码文件中参与link,否则在链接时会提示符号重复。当然文件后缀名称可以任意修改。

引用本地文件

大型项目常常伴随着自动化构建。一个典型的场景是自动化脚本计算好版本号、时间戳等信息并写入文本文件,C程序通过#include的方式引入,不限于常量数值、常量字符串、结构体等。

include数值文件

uint64_t easeapi_timestamp = {
    #include "file/easeapi_timestamp.txt"
};

include字符串文件

const char *easeapo_version = {
    #include "file/version.txt"
};

include结构体文件

file/easeapi_struct.txt文件内容如下:

{"iOS", "https://easeapi.com/blog/tags/iOS.html"},
{"GIT", "https://easeapi.com/blog/tags/Git.html"},

使用#include引用:

typedef struct _EaseapItem {
    string name;
    string url;
} EaseapItem;

const EaseapItem easeapItems[] = {
    #include "file/easeapi_struct.txt"
};