使用带有宏名称的字符串获取宏的值

Get the value of a macro using a string with macro name

我有一组宏定义,名称只在“C_”和“_E”之间的数字上变化。我需要的是一个宏,它获取一个整数变量和 returns 相应宏定义的整数值,如果它存在,如果它不存在,它 returns "-1" 或者给出一个编译错误。那可能吗?我需要的代码是这样的:

#include <stdio.h>

#define C_1_E 4
#define C_2_E 2
#define C_3_E 0
#define C_4_E 420

#define STR(x) #x
#define STR_MACRO(x) "C_" STR(x) "_E"

#define MACRO_VAL(x) ... // return the value of the macro C_x_E when x=1,2,3 or 4

void main() {
  uint8_t n;
  for(n=1;n<=4;n++) printf("val %u: %u\n",n, MACRO_VAL(STR_MACRO(n)));
}

预期输出:

val 1: 4
val 2: 2
val 3: 0
val 4: 420

根据我的搜索,这是不可能的,但我可以发誓我确实遇到过一次这个解决方案,但当时我并不需要它,尽管我认为它可能会有帮助。

如果你需要专门有一个宏,而不是一个函数,那么扩展为函数调用的宏肯定也不是acceptable。仅当您需要预处理器在编译时将宏编号转换为宏扩展时,这对我才有意义。这似乎不是示例代码所必需的,但在某些情况下确实需要它。

这太糟糕了,因为 C 预处理器无法提供实现您所要求的方法。变量在编译时不存在或没有值,因此编译器无法在编译时将变量名转换为它所代表的值,更不用说从中构建宏名称,更不用说扩展这样的替换文本的名称。

但是,您可以使用数字文字而不是变量来完成此操作:

#define EXPAND(x) x
#define MACRO_VAL(n) EXPAND(C_ ## n ## _E)

printf("val %d: %d\n",n, 1, MACRO_VAL(1));
printf("val %d: %d\n",n, 2, MACRO_VAL(2));
printf("val %d: %d\n",n, 3, MACRO_VAL(3));
printf("val %d: %d\n",n, 4, MACRO_VAL(4));

如果您尝试使用不产生已定义宏名称或 in-scope 变量的参数来扩展它,那么(几乎肯定)将产生 compile-time 错误以引用一个未定义的变量。


如果 run-time 评估毕竟是 acceptable,那么您可以编写一个函数来完成它(如果需要,您可以将其包装在宏中):

#define MACRO_VAL(n) lookup_macro(n)

#define EXPAND(x) x
#define MACRO_CASE(i) case i: return EXPAND(C_ ## i ## _E)
int lookup_macro(int n) {
    switch (n) {
       MACRO_CASE(1);
       MACRO_CASE(2);
       MACRO_CASE(3);
       MACRO_CASE(4);
       default: return -1;
    }
}

对于定义的案例未涵盖的算术参数,这将 return -1。

您还可以考虑查找 table,可能包含在一个函数中,但是如果参数不匹配任何宏,则需要更多代码来提供 -1 结果,特别是如果宏编号不是全部连续的,或者其中最少的编号事先不知道。

令牌粘贴方法不合适,因为 x 是一个变量名。

这里有一个简单的方法,只要宏参数是一个没有副作用的表达式就可以使用:

#include <stdio.h>

#define C_1_E 4
#define C_2_E 2
#define C_3_E 0
#define C_4_E 420

// return the value of the macro C_x_E when x=1,2,3 or 4
#define MACRO_VAL(x)  ((x) == 1 ? C_1_E : \
                       (x) == 2 ? C_2_E : \
                       (x) == 3 ? C_3_E : \
                       (x) == 4 ? C_4_E : -1)

int main() {
    int n;
    for (n = 1; n <= 4; n++)
        printf("val %u: %u\n", n, MACRO_VAL(n));
    return 0;
}