为什么在 C 预处理器宏中嵌套连接扩展失败?

Why does nested expanding with concatenation fail inside a C preprocessor macro?

我目前正在自动创建内容几乎相同的多个函数。 这是该项目的最小示例:

#include <stdio.h>

#define _macro_print(m) printf("Value: %x\n", test_##m);
#define _macro_var_def(m) int test_##m = m;

// Repeat macro d n-times
#define BSV_REPEAT(n, d) _BSV_REPEAT_##n(d)
#define _BSV_REPEAT_1(d) _macro_##d(0)
#define _BSV_REPEAT_2(d) _BSV_REPEAT_1(d)_macro_##d(1)
#define _BSV_REPEAT_3(d) _BSV_REPEAT_2(d)_macro_##d(2)
#define _BSV_REPEAT_4(d) _BSV_REPEAT_3(d)_macro_##d(3)

#define NUMBER_OF_TIMES 4

int main() {
    BSV_REPEAT(4, var_def)
    // NUMBER_OF_TIMES
    BSV_REPEAT(4, print)
    //BSV_REPEAT(NUMBER_OF_TIMES, print)
    return 0;
}

_macro_print 背后的实际宏要复杂得多,因此不可能在运行时使用 for 循环或类似的东西来完成。

在实际项目中,我多次使用 BSV_REPEAT 宏和不同的宏,但重复次数始终相同。当然,我想为这个数字创建一个定义,以便以后可以轻松更改它。

当我使用定义 NUMBER_OF_TIMES CLion 报告如下 message and the program can not longer be compiled.

我现在的问题是如何解决这个问题?有没有办法强制更早地评估 NUMBER_OF_TIMES?

您需要控制展开顺序。
为此,引入一个专门的附加层来扩展和连接:

#define _macro_print(m) printf("Value: %x\n", test_##m);
#define _macro_var_def(m) int test_##m = m;

#define CONCAT(x,y) x##y
// Repeat macro d n-times
#define BSV_REPEAT(n, d) CONCAT(_BSV_REPEAT_,n)(d)
#define _BSV_REPEAT_1(d) CONCAT(_macro_,d)(0)
#define _BSV_REPEAT_2(d) _BSV_REPEAT_1(d)CONCAT(_macro_,d)(1)
#define _BSV_REPEAT_3(d) _BSV_REPEAT_2(d)CONCAT(_macro_,d)(2)
#define _BSV_REPEAT_4(d) _BSV_REPEAT_3(d)CONCAT(_macro_,d)(3)

#define NUMBER_OF_TIMES 4

int main() {
    BSV_REPEAT(4, var_def)
    NUMBER_OF_TIMES
    BSV_REPEAT(4, print)
    BSV_REPEAT(NUMBER_OF_TIMES, print)
    return 0;
}

上面带有 -E 选项的输出:

int main() {
    int test_0 = 0;int test_1 = 1;int test_2 = 2;int test_3 = 3;
    4
    printf("Value: %x\n", test_0);printf("Value: %x\n", test_1);printf("Value: %x\n", test_2);printf("Value: %x\n", test_3);
    printf("Value: %x\n", test_0);printf("Value: %x\n", test_1);printf("Value: %x\n", test_2);printf("Value: %x\n", test_3);
    return 0;
}

并且请改掉使用以“_”开头的标识符的习惯,它们是保留的。