如何通过C预处理器实现带例外规则的函数列表条件编译?
问题描述
我有一个通过Makefile生成并导出到文件的函数列表,内容如下:
DEF(foo) DEF(bar) DEF(baz)
原本的用法是通过以下方式定义函数列表:
#define DEF(name) void name(); #include "generated_list.inc"
现在需要为该生成列表添加例外规则:例如定义#define DONT_DEF_baz后,baz会被忽略。
原本设想递归预处理器实现如下,但C语言不支持该写法:
#define DEF(name) \ #ifndef DONT_DEF_ ## name \ void name(); \ #endif \
请问是否有可行的替代方案实现该效果?
可行替代方案
方案1:基于C预处理器的间接展开实现
C预处理器不允许在宏定义中直接嵌套#ifndef,但可以通过标识符拼接+间接宏展开的方式绕开这个限制,具体步骤如下:
定义辅助宏
// 拼接DONT_DEF_前缀和函数名,生成目标标识符 #define CONCAT(a, b) a ## b #define DONT_DEF_SYM(name) CONCAT(DONT_DEF_, name) // 核心:根据标识符是否定义,选择输出内容 #define IF_NOT_DEFINED(sym, output) \ _IF_NOT_DEFINED_HELPER(_DEFINED_##sym, output) #define _IF_NOT_DEFINED_HELPER(flag, output) \ _IF_NOT_DEFINED_##flag(output) #define _IF_NOT_DEFINED__DEFINED_(output) output // 标识符未定义时输出内容 #define _IF_NOT_DEFINED__DEFINED_1(output) // 标识符已定义时无输出 // 最终的DEF宏:仅当DONT_DEF_xxx未定义时,生成函数声明 #define DEF(name) IF_NOT_DEFINED(DONT_DEF_SYM(name), void name();)
使用方式
在导入生成列表前,定义需要忽略的函数对应的宏即可:
// 忽略baz的函数声明 #define DONT_DEF_baz 1 #include "generated_list.inc"
此时预处理器会自动跳过baz的声明,保留foo和bar的函数原型。
方案2:在Makefile生成阶段过滤(更简洁)
既然函数列表由Makefile生成,也可以直接在生成阶段就过滤掉需要忽略的函数,无需修改C预处理器逻辑:
- 在Makefile中指定需要忽略的函数:
# 定义需要忽略的函数列表 IGNORE_FUNCS := baz
- 生成
generated_list.inc时,通过grep过滤掉这些函数:
generated_list.inc: your_input_source.txt # 用正则匹配需要忽略的DEF行并过滤 grep -v -E "^DEF\($(subst $(space),|,$(IGNORE_FUNCS))\)" $< > $@
这种方式直接从源头排除不需要的函数声明,逻辑更直观,适合场景简单的情况。
内容的提问来源于stack exchange,提问作者shoosh
相关产品推荐
相关产品推荐

