我想编写评估的预处理器函数/数组 编译时间。例如,如果我定义
#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;
显然,我们必须使用文字作为参数。这可能吗?
答案 0 :(得分: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来提取预处理器组件。
答案 1 :(得分:2)
标准C预处理器无法满足您的需求。为了可靠地获得这种行为,您将需要一个更强大的非标准预处理工具。但是,我不太熟悉可以指导您选择哪一个。
虽然在第二种情况下,您仍然可以在大多数现代编译器上获得所需的效果。例如:
#define MYMAP(n) (((n) == 1) ? 5 : 2)
int x = MYMAP(4);
仍将呈现给编译器:
int x = ((4 == 1) ? 5 : 2);
但是编译器本身,如果它是一个合理的现代编译器并允许它进行优化,可能会注意到这个表达式可以在编译时进行评估,并且会发出与
相同的代码。int x = 2;
但是,保证没有任何东西可以让编译器执行此优化。
答案 2 :(得分:2)
在C99(你真的需要,C89不会这样做)你可以做类似
的事情#define MyMap(N) (((int const[]){ 3, 4, 5, 6, 7})[N])
如果你的类型是int
,但任何其他类型都可以。奇怪的事情(int const[]){ 3, 4, 5, 6, 7}
被称为复合文字。基类型的const
告诉编译器它不会被修改,并且他可以将具有相同内容的所有事件别名化为同一个固定位置。
编辑,在caf的评论之后:
通常,对于这种方法,大多数编译器都能够完全优化对数组的任何引用,前提是N
是一个可以在编译时计算的表达式,例如固定值7
或{{ 1}}左右。
如果不是这种情况,编译器必须在某处创建数组对象。使用'a'
,他可以只生成一个副本,无论您在代码中调用宏的频率如何。当他设法这样做时,数组的初始化将在编译时完成,因此不会有编译时间开销。
我检查了我在机器上的三个编译器:
const
和gcc
分配数组
堆栈和每个单独的
调用clang
,错误,因为开销与数组的大小成正比。MyMap
静态分配数组
但为每个电话创建一个新副本
到opencc
,更好,但还不理想。答案 3 :(得分:0)
myarr for chars我能做到
#define MYARR(x) ("1234567"[x])
还在思考一下。 Mymap是
#define MYMAP(n) (n == 1 ? 5 : 2)
答案 4 :(得分: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.