【问题标题】:Const array initialization from other const arrays来自其他 const 数组的 const 数组初始化
【发布时间】:2013-10-21 15:11:03
【问题描述】:

如下代码sn-p:

static const double foo[3] = { 1.0, 2.0, 3.0 };
static const double bar[3] = { foo[0]*foo[0], 3*foo[1], foo[2]+4.0 };

生成一个编译器错误,指出初始化值不是常量。

有一些数据数组(可以假定一个固定大小)和其他一些数据数组,它们以相当简单的方式依赖和相关,这对于在编译时而不是运行时进行预计算很有用。但由于可能需要更改源数据,我希望此类更改避免手动重新计算依赖数组。

我想有人可以制作一些生成 .h 文件的实用程序,但此时我很好奇——有没有办法做这样的事情(只输入一次 const 数组的数据,但有几个其他 const 数组依赖于它们)在 C 预处理器中比(比如说)为每个源数组的每个元素定义一个预处理器宏更干净?

附:如果有一些预处理器库可以做这样的事情,我真的很感激一个代码示例。

【问题讨论】:

    标签: c arrays c-preprocessor


    【解决方案1】:

    听起来您的原始数组实际上是一个特殊常量列表,而foo 只是它们的集合。

    您可以使用定义和构造数组以供以后在程序中使用来实现类似的功能:

    #define SpecialA 1.0
    #define SpecialB 2.0
    #define SpecialC 3.0
    
    static const double foo[3] = { SpecialA, SpecialB, SpecialC };
    static const double bar[3] = { SpecialA*SpecialA, 3*SpecialB, SpecialC+4.0 };
    

    【讨论】:

    • 确实如此,但由于最终会有一个度量标准的垃圾负载,我很好奇一种方法,它比为每个宏单独制作单独的预处理器宏更干净。不过,如果没有,我可能最终会做这样的事情。
    • 公制垃圾负载是如何生成的?也许它应该以#define 形式而不是作为数组生成?
    【解决方案2】:

    在摆弄了一些预处理器之后,结果证明它比我想象的要容易。目标是只为源数组输入一次数据,同时避免单独定义每个条目。这可以通过将数组的内容定义为预处理器宏来实现:

    #define FOO      1.0, 2.0, 3.0
    static const double foo[] = { FOO };
    static const double bar[] = { ARR_EL(0,FOO)*ARR_EL(0,FOO), \
                                  3.0*ARR_EL(1,FOO), ARR_EL(2,FOO)+4.0 };
    /* Whatever else */
    

    其中的辅助宏如下:

    /* ARR_EL(n,...) returns nth element of the array */
    #define ARR_EL(n,...)      ARR_EL0(ARR_BEGIN(n,__VA_ARGS__))
    #define ARR_EL0(...)       ARR_ELX(__VA_ARGS__)
    #define ARR_ELX(e0,...)    (e0)
    
    /* ARR_BEGIN(n,...) returns subarray starting with nth element */
    #define ARR_BEGIN(n,...)   ARR_BEGIN##n(__VA_ARGS__)
    #define ARR_BEGIN0(...)    __VA_ARGS__ /* Why is this even here? */
    #define ARR_BEGIN1(...)    ARR_BEGINX(__VA_ARGS__)
    #define ARR_BEGINX(e0,...) __VA_ARGS__
    #define ARR_BEGIN2(...)    ARR_BEGIN1(ARR_BEGIN1(__VA_ARGS__))
    #define ARR_BEGIN3(...)    ARR_BEGIN2(ARR_BEGIN1(__VA_ARGS__))
    #define ARR_BEGIN4(...)    ARR_BEGIN3(ARR_BEGIN1(__VA_ARGS__))
    /* Extendible in the obvious way */
    

    在 gcc (cpp 4.1.1) 和 tcc 中测试,但我相信这应该都是标准的 C99。

    如果没有 ARR_ELXARR_BEGINX 宏提供的额外步骤,预处理器有时会将 FOO 视为单个参数。

    【讨论】:

      猜你喜欢
      • 2014-08-08
      • 2013-04-04
      • 1970-01-01
      • 2015-01-28
      • 2011-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多