在 C 编译时评估的预处理器函数

问题描述 投票:0回答:5

我想编写在以下位置评估的预处理器函数/数组 编译时间。例如,如果我定义

#define MYARR[] {5,4,3,2,1,0}

然后,代码

int x = R[0];

应呈现为

int x = 5;

给编译器。 (当然索引中只能使用文字)。 如果代码大小/内存很关键并且我们不想这样做,那么这一点很重要 存储

MYARR
,但我们需要它来方便编码。

编译时函数也不错。例如,类似

#define MYMAP(n)
#if n==1
5
#else
2

所以,声明

int x = MYMAP(4);

应以如下方式呈现给编译器:

int x = 2;

显然,我们必须使用文字作为参数。这可能吗?

c c-preprocessor
5个回答
5
投票
当然有可能。虽然您可以手动执行此操作,但

Boost.Preprocessor已经为您提供了所需的工具:

#include <boost/preprocessor.hpp> #define SEQ (5)(4)(3)(2)(1)(0) int x = BOOST_PP_SEQ_ELEM(0, SEQ);
...转变为:

int x = 5;
它还包括算术、比较和控制结构,如 

IF

FOR
FOR_EACH
、枚举……您只需记住,您可以使用的数据类型相当有限。

再次利用

Boost.PP,你的第二个例子可以像这样完成:

#define MYMAP(x) BOOST_PP_IF(BOOST_PP_EQUAL(x, 1), 5, 2)
你当然可以手动实现Boost.PP所做的事情,但考虑到这需要时间和精力,我个人不会打扰。

作为 C 用户,您不会对 Boost 的其余部分感兴趣,因此您可能需要使用

bcp 来提取预处理器组件。


2
投票
标准 C 预处理器不会做你想做的事。为了可靠地获得这种行为,您将需要一个更强大的非标准预处理工具。然而,我对可用的内容还不够熟悉,无法引导您找到您可能想要的内容。

尽管在第二种情况下,您仍然可以在大多数现代编译器上获得您想要的效果。例如:

#define MYMAP(n) (((n) == 1) ? 5 : 2) int x = MYMAP(4);

仍将

呈现给编译器为:

int x = ((4 == 1) ? 5 : 2);

但是编译器本身,如果它是一个合理的现代编译器并且您允许它优化,则可能会注意到这个表达式可以在编译时求值,并且会发出与

相同的代码

int x = 2;

但是,没有任何东西可以

保证编译器将执行此优化。


2
投票
在C99中(你确实需要它,C89不会这样做)你可以做类似的事情

#define MyMap(N) (((int const[]){ 3, 4, 5, 6, 7})[N])

只要您的类型是

int

,但任何其他类型都可以。奇怪的东西 
(int const[]){ 3, 4, 5, 6, 7}
 被称为复合文字。基本类型中的 
const
 告诉编译器它不会被修改,并且他可以将所有具有相同内容的实例别名到相同的固定位置。

编辑,咖啡馆评论后: 一般来说,对于这种方法,大多数编译器将能够完全优化对数组的任何引用,前提是 N

 是可以在编译时计算的表达式,例如固定值 
7
'a'
 等。 

如果不是这种情况,编译器必须在某处创建数组对象。有了

const

,他就可以只生成它的一份副本,无论您在代码中调用宏的频率如何。当他设法这样做时,数组的初始化将在编译时完成,因此不会有编译时间开销。

我检查了我机器上的三个编译器:

  • gcc
    clang
     分配数组
    堆栈和每个单独的这个
    调用 
    MyMap
    bad,因为开销与数组的大小成正比。
  • opencc
     静态分配数组
    但为每次调用创建一个新副本
    到 
    MyMap
    更好,但还不够理想。

0
投票
myarr 我能做的事情

#define MYARR(x) ("1234567"[x])

仍在思考整数。我的地图是

#define MYMAP(n) (n == 1 ? 5 : 2)
    

0
投票
没有标准的预处理器命令可以按照您想要的方式处理数组。我建议你使用 const。

static const int R[] = {5,4,3,2,1,0}; ... int a = R[0];

那么MYMAP问题...

#define MYMAP(n) ((n)==1?5:2) ... int a = MYMAP(1); // equals 5.
    
© www.soinside.com 2019 - 2024. All rights reserved.