能否利用预处理器宏的值生成新令牌?C预处理器技术疑问
问题描述
用户尝试通过C预处理器实现用宏定义的值生成函数名的需求,具体场景如下:
现有可运行代码
#include <stdio.h> #define ONE 1 #define TWO 2 #define OOPS 42 #define DEF_FOO(x) void foo_##x(void){ printf(#x" %d\n",x);} DEF_FOO(ONE); DEF_FOO(TWO); DEF_FOO(OOPS); int main() { foo_ONE(); foo_TWO(); foo_OOPS(); return 0; }
对应输出
ONE 1 TWO 2 OOPS 42
期望实现的目标
用户希望定义DEF_BAR宏,让生成的函数名使用宏的数值(如1、2、42)而非宏名,示例代码框架如下:
#include <stdio.h> #define ONE 1 #define TWO 2 #define OOPS 42 #define DEF_BAR(x) void bar_??x??(void){ printf(#x" %d\n",x);} DEF_BAR(ONE); DEF_BAR(TWO); DEF_BAR(OOPS); int main() { bar_1(); bar_2(); bar_42(); return 0; }
可接受的输出
两种输出均符合要求:
输出1:
ONE 1 TWO 2 OOPS 42
输出2:
1 1 2 2 42 42
用户核心疑问:是否可以使用预处理器令牌的值来创建新令牌?理论上预处理器应该知晓该值,对吗?
解答
标准C预处理器无法直接实现用宏的值生成新令牌的需求。
核心原因是预处理器的处理顺序和令牌拼接规则:
- 当宏
DEF_BAR(x)接收参数ONE时,预处理器会先展开ONE得到数值1,但令牌拼接操作(##)的处理对象是传入的原始令牌符号(也就是ONE),而非展开后的数值。 - 预处理器虽然知晓宏的数值,但它没有机制把数值转换为对应的标识符令牌,再进行拼接。标识符的构造只能基于原始的符号令牌,没法直接用宏展开后的数值结果。
如果非要达成类似效果,只能通过间接手段:
- 手动建立数值到宏名的反向映射,比如额外定义
#define VAL_1 ONE,再通过多层宏展开间接实现函数名拼接,但这本质是手动维护映射关系,并非自动提取宏值生成。 - 借助外部代码生成工具(如Python脚本),提前解析宏定义并生成对应的函数代码,再嵌入到项目中。
内容的提问来源于stack exchange,提问作者Guillaume D
相关产品推荐
相关产品推荐

