代码之家  ›  专栏  ›  技术社区  ›  highBandWidth

在C中编译时计算的预处理器函数

  •  6
  • highBandWidth  · 技术社区  · 16 年前

    我想编写在 编译时间。例如,如果我定义

    #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;
    

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

    5 回复  |  直到 10 年前
        1
  •  5
  •   Georg Fritzsche    16 年前

    当然有可能。虽然你可以手动操作, 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

    利用增强.PP同样,你的第二个例子可以这样做:

    #define MYMAP(x) BOOST_PP_IF(BOOST_PP_EQUAL(x, 1), 5, 2)
    

    你当然可以手动实现什么增强.PP是的,但考虑到这需要的时间和精力,我个人不会费心。

    作为一个C用户,您不会对Boost的其余部分感兴趣,因此您可能希望使用 bcp 提取预处理器组件。

        2
  •  2
  •   Tyler McHenry    16 年前

    标准的C预处理器不会做你想做的事情。为了可靠地获得这种行为,您需要一个更强大的、非标准的预处理工具。然而,我不太熟悉什么是可用的,以指导你到哪一个你可能想要的。

    不过,在第二种情况下,您仍然可以在大多数现代编译器上获得所需的效果。例如:

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

    仍将是 作为:

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

    int x = 2;
    

    但是,没有什么 编译器将执行此优化。

        3
  •  2
  •   Jens Gustedt    16 年前

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

    如果你的类型是 int (int const[]){ 3, 4, 5, 6, 7} 称为复合文字。这个 const 在那里,for基类型告诉编译器它将不会被修改,并且他可以将所有具有相同内容的实例别名到相同的固定位置。

    编辑,在caf的评论之后: N 7 或 'a' 差不多吧。

    常数 他可以被允许只生成它的一个副本,不管您在代码中调用宏的频率有多高。当他设法做到这一点时,数组的初始化将在编译时完成,因此不会有编译时开销。

    • gcc 和 clang 一堆一堆的 呼叫 MyMap ,
    • opencc 静态分配数组 但每次通话都会创建一个新的副本 到 , 更好的
        4
  •  0
  •   pm100    16 年前

    我可以做些什么

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

    仍在思考问题。我的地图是

    #define MYMAP(n) (n == 1 ? 5 : 2)
    
        5
  •  0
  •   tidwall    16 年前

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

    那么我的地图问题。。。

    #define MYMAP(n) ((n)==1?5:2)
    ...
    int a = MYMAP(1); // equals 5.