如何在预处理期间将常量表达式更改为文字数字? (使用海合会)
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?可以的话怎么定义?
注:
- 我使用 GCC 编译器,所以可以使用 gnu c 扩展。
- 仅在预处理期间。我知道在编译期间该怎么做。但它不一定是宏。
- 另外,是否可以将字符串常量表达式更改为文字字符串?以及如何去做?
无法完成。在应用任何 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]();
代码如下:
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?可以的话怎么定义?
注:
- 我使用 GCC 编译器,所以可以使用 gnu c 扩展。
- 仅在预处理期间。我知道在编译期间该怎么做。但它不一定是宏。
- 另外,是否可以将字符串常量表达式更改为文字字符串?以及如何去做?
无法完成。在应用任何 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]();