如何在预处理期间将常量表达式更改为文字数字? (使用海合会)

How to change a constant expression to a literal number during preprocessing? (use gcc)

代码如下:

void f1(){
    /* ... */
}

void f2(){
    /* ... */
}

int main()
{
    const int n=2;
    USE(f, n)();
    return 0;
}

希望它能调用f2()。

如果我们只定义为:

#define PASTE(a,b) a##b
#define USE(a,b) PASTE(a,b)

它将调用 fn()。所以我们应该定义一个新的宏来将 n 更改为 2,例如:

#define PASTE(a,b) a##b
#define CHANGE_constexpr_TO_literal(n)  // I don't know how to define
#define USE(a,b) PASTE(a,CHANGE_constexpr_TO_literal(b))

那么 CHANGE_constexpr_TO_literal(n) 的扩展将是 2 .

是否可以定义宏来强制 constexpr n 成为 literal n?可以的话怎么定义?

注:

无法完成。在应用任何 C 语法规则之前,预处理器仅对标记进行操作。因此 const int n 未被 甚至在 USE 宏即将展开时被解析。

解决方法是将 USE() 定义为条件运算符链,根据 n 选择所需的函数指针。

#define USE(f, n) (    \
   (n == 0) ? f ## 0 : \
   (n == 1) ? f ## 1 : \
   (n == 2) ? f ## 2 : \
   NULL)

这种方法的优点是,如果 n 是常量表达式,那么 USE() 的值也是常量表达式。

顺便说一句。在标准 C 中,const int n = 2; 不会 使 n 成为常量表达式。使用宏或枚举:

#define n 2

enum { n = 2 };

我们仍然使用 #define 常量而不是类型安全的 const 变量的主要原因是前者可以在预处理器宏中使用。 C 中的变量永远不是编译时常量,它的值不能被预处理器访问。

所以解决方法是将 const 变量更改为 #define 宏,否则无法完成:

#include <stdio.h>

void f1(void){
    puts(__func__);
}

void f2(void){
    puts(__func__);
}

#define PASTE(f,n) f##n
#define USE(f,n) PASTE(f,n)

#define n 2

int main (void)
{
    USE(f,n)();  // this is btw a horrible poor way of writing C code
    return 0;
}

一个更明智和更易读的解决方案是函数指针 table:

typedef void func_t (void);

static func_t* const f[] = { f0, f1, f2 };
...
f[n]();