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

如何通过运行时变量索引访问C语言中按序列定义的宏常量

不能直接通过运行期变量用宏拼接的方式访问对应值,原因你已经提到了,宏的所有处理(包括令牌拼接##)都发生在编译前的预处理阶段,此时运行期变量的取值完全未知,TEST(i)会被直接拼接为TESTi,而你的代码里没有定义这个宏,自然会报错。

下面是比switch分支扩展性更好的实现方案:

方案1:静态数组映射(适合序号连续的场景)

你当前的序号是0~9连续取值,直接做一个常量数组做映射是性能最高、实现最简单的方案:

// 预编译阶段就完成数组初始化
static const int test_map[] = {TEST0, TEST1, TEST2, TEST3, TEST4, TEST5, TEST6, TEST7, TEST8, TEST9};
// 运行期直接用下标访问,注意加边界校验避免越界
int get_test_val(int idx) {
    if (idx < 0 || idx >= sizeof(test_map)/sizeof(test_map[0])) {
        // 自定义错误处理,比如返回-1
        return -1;
    }
    return test_map[idx];
}

访问的时候直接调用get_test_val(idx)即可,比switch写法简洁得多。

方案2:X宏(扩展性最优,适合需要频繁增删宏的场景)

如果后续需要频繁新增TEST类的宏,不想每次新增都手动改数组/switch代码,可以用X宏技巧实现一次定义多处复用:
首先统一维护所有序号列表:

#define TEST_ID_LIST \
    X(0) \
    X(1) \
    X(2) \
    X(3) \
    X(4) \
    X(5) \
    X(6) \
    X(7) \
    X(8) \
    X(9)

通过这个列表自动生成映射数组,完全不用手动写每个元素:

static const int test_map[] = {
#define X(id) [id] = TEST##id,
    TEST_ID_LIST
#undef X
};

后续需要新增TEST10,只需要在TEST_ID_LIST里加一行X(10)即可,映射数组会自动同步新增TEST10的取值,没有冗余代码,可扩展性极强。

序号不连续的适配方案

如果序号不是连续的整数,可以把映射表改成结构体数组,用标准库的bsearch做二分查找,性能也远高于长switch分支:

typedef struct {
    int id;
    int val;
} TestMap;
static const TestMap test_map[] = {
#define X(id) {id, TEST##id},
    TEST_ID_LIST
#undef X
};
// 调用bsearch前先对数组按id排序即可

内容的提问来源于stack exchange,提问作者Lolo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 12:36:03