You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 11:50:22