如何在C预处理器中字符串化宏且不展开已定义组件
解决方案:避免预处理器展开字符串宏中的已定义组件
核心问题根源
你遇到的问题本质是:当用-DFOO=GNU/linux这类无外层引号的方式传递参数时,预处理器会把linux当作独立标识符展开成预定义值;但如果传递的是带外层引号的字符串常量,内部的字符会被视为字符串内容,不会被预处理器解析为宏。
具体实现步骤
1. 在Automake中正确传递带引号的字符串
在Makefile.am里,通过shell转义传递带双引号的字符串参数:
AM_CPPFLAGS = -DFOO='"GNU/linux"'
GCC最终会收到-DFOO="GNU/linux",此时FOO被预处理器定义为字符串常量"GNU/linux",内部的linux是字符串的一部分,不会被展开。
2. 调整C代码直接使用宏
不需要再依赖双层STRINGIFY宏,直接将宏作为字符串常量使用即可:
#include <stdio.h> int main() { printf("%s\n", FOO); return 0; }
3. 兼容原有STRINGIFY宏的写法
如果现有代码必须保留STRINGIFY宏,可以修改宏定义为直接引用参数(避免触发额外展开):
#define STRINGIFY(x) x const char *foo = STRINGIFY(FOO);
由于FOO本身已是字符串常量,STRINGIFY(FOO)会直接返回该常量,不会解析内部内容。
额外注意事项
- 如果传递的字符串包含双引号,需要在Automake中额外转义,比如传递
"GNU\"linux",要写成-DFOO='"GNU\\"linux"'。 - 绝对不要使用
-DFOO=GNU/linux这种无外层引号的写法,否则预处理器会把linux当作独立标识符展开。
内容的提问来源于stack exchange,提问作者umläute
相关产品推荐
相关产品推荐

