如何正确字符串化并拼接宏参数?__failure宏实现咨询
解决GCC宏的字符串化与拼接问题:实现
__failure()调试输出 刚好之前处理过类似的宏定义需求,核心难点在于预定义宏的展开顺序——直接用#字符串化操作符的话,预处理器会把__LINE__这类宏名本身当作字符串,而不是先替换成实际的行号/文件名/函数名。必须用间接展开的技巧来解决这个问题,下面一步步给你实现:
1. 先搞懂为什么需要间接字符串化
GCC的__FILE__、__LINE__、__FUNCTION__都是预处理阶段才会替换的宏,但如果直接写#__LINE__,预处理器只会输出字符串"__LINE__",而不是当前行号的字符串。这时候需要一层中间宏,让__LINE__先完成展开,再被字符串化。
2. 实现辅助宏:字符串化与拼接
先定义两个辅助宏处理字符串化,再定义消息拼接的宏:
// 直接字符串化(参数不会先展开) #define STRINGIFY(x) #x // 间接字符串化:让参数先展开,再字符串化 #define STRINGIFY_INDIRECT(x) STRINGIFY(x) // 拼接成 "filename:line:function" 格式的字符串 #define FAILURE_INFO \ __FILE__ ":" STRINGIFY_INDIRECT(__LINE__) ":" __FUNCTION__
这里的关键逻辑:
__FILE__本身就是字符串字面量,不需要额外处理__FUNCTION__在GCC中会被展开为当前函数名的字符串(C99标准的__func__也可以用,兼容性更好)__LINE__必须通过STRINGIFY_INDIRECT先展开成行号,再转成字符串- C预处理器会自动拼接相邻的字符串字面量,所以三个部分放在一起就会变成完整的格式
3. 最终的__failure()宏
把上面的消息封装成你需要的宏,比如让它打印到标准错误流:
#define __failure() \ fprintf(stderr, "Error occurred at: %s\n", FAILURE_INFO)
完整测试示例
#include <stdio.h> #define STRINGIFY(x) #x #define STRINGIFY_INDIRECT(x) STRINGIFY(x) #define FAILURE_INFO \ __FILE__ ":" STRINGIFY_INDIRECT(__LINE__) ":" __FUNCTION__ #define __failure() \ fprintf(stderr, "Error occurred at: %s\n", FAILURE_INFO) void demo_func() { __failure(); // 这里会输出当前文件、行号、demo_func } int main() { demo_func(); __failure(); // 这里会输出当前文件、行号、main return 0; }
编译运行效果
用GCC编译后运行,输出会是这样:
Error occurred at: test.c:11:demo_func Error occurred at: test.c:16:main
完全符合你期望的filename:line:function格式。
额外注意点
- 如果需要兼容C标准而非仅GCC,建议用
__func__替代__FUNCTION__(两者在GCC中效果一致,但__func__是C99标准规定的) - 间接展开的核心是利用预处理器的优先级:当宏参数没有被
#或##直接操作时,参数会先展开,再代入外层宏
内容的提问来源于stack exchange,提问作者Karim Manaouil
相关产品推荐
相关产品推荐

