如何实现C语言中关联函数与文件名的WHERE_AM_I宏?
问题:实现根据文件和函数自动取值的
WHERE_AM_I宏 需要在C语言中实现一个WHERE_AM_I宏,要求:
- 在AAA文件的
foo1函数中调用时,输出预定义的FOO1_AAA的值1 - 在BBB文件的
foo2函数中调用时,输出预定义的FOO2_BBB的值2
最初尝试直接定义普通宏失败,转而用GEN函数宏,但通过__FILE__和__func__拼接的方式无法正常工作,希望找到可行方法让宏生成对应函数字符串达成需求。
用户提供的目标代码示例
#define FOO1_AAA 1 #define FOO2_BBB 2 #define WHERE_AM_I ??? void foo1() // 在AAA文件中 { printf("%d\n", WHERE_AM_I); } // 期望输出: 1 void foo2() // 在BBB文件中 { printf("%d\n", WHERE_AM_I); } // 期望输出:2
用户尝试的GEN宏代码
#define GEN(FILE, FUNC, VAL) inline int FILE##_##FUNC(){return VAL;} GEN(myfile, myfunc, 10) printf("%d\n", myfile_myfunc()); // 输出10,这部分正常 // 但尝试以下写法时失败 #define GET_PP(A, B) A##_##B #define GET_VV GET_PP(__FILE__, __func__) GEN(myfile, myfunc) void myfunc(){ // 在myfile文件中 printf("%d\n", GET_VV); } // 无法正常工作
解决方案
核心问题在于__FILE__展开后是带双引号的字符串(比如"AAA"),__func__也是字符串常量,直接用##拼接会产生无效的C标识符,预处理器无法处理这种拼接。下面是可行的实现方案:
步骤1:为每个文件定义无引号的标识宏
在AAA文件开头添加:
#define FILE_ID AAA
在BBB文件开头添加:
#define FILE_ID BBB
步骤2:实现WHERE_AM_I宏
通过两层宏展开,先确保__func__和FILE_ID先被替换成对应标识符,再拼接成目标宏名:
// 辅助宏:直接拼接两个标识符 #define CONCAT(A, B) A##_##B // 间接展开宏:确保参数先被替换,再执行拼接 #define CONCAT_INDIRECT(A, B) CONCAT(A, B) // 最终宏:拼接函数名和文件标识,获取对应预定义值 #define WHERE_AM_I CONCAT_INDIRECT(__func__, FILE_ID)
完整可运行代码示例
AAA文件(aaa.c)
#include <stdio.h> #define FILE_ID AAA #define FOO1_AAA 1 #define CONCAT(A, B) A##_##B #define CONCAT_INDIRECT(A, B) CONCAT(A, B) #define WHERE_AM_I CONCAT_INDIRECT(__func__, FILE_ID) void foo1() { printf("%d\n", WHERE_AM_I); // 输出1 }
BBB文件(bbb.c)
#include <stdio.h> #define FILE_ID BBB #define FOO2_BBB 2 #define CONCAT(A, B) A##_##B #define CONCAT_INDIRECT(A, B) CONCAT(A, B) #define WHERE_AM_I CONCAT_INDIRECT(__func__, FILE_ID) void foo2() { printf("%d\n", WHERE_AM_I); // 输出2 }
主文件(main.c)
extern void foo1(); extern void foo2(); int main() { foo1(); foo2(); return 0; }
为什么之前的方法失效?
__FILE__展开后是带双引号的字符串,直接拼接会生成类似"AAA"_foo1的无效标识符__func__属于字符串常量,同样无法直接与普通标识符拼接- 自定义的
FILE_ID是不带引号的纯标识符,能和__func__展开后的函数名(也是标识符)正常拼接,最终匹配到预定义的FOO1_AAA、FOO2_BBB宏
内容的提问来源于stack exchange,提问作者user487363
相关产品推荐
相关产品推荐

