从其他const数组初始化const数组

时间:2013-10-14 04:52:35

标签: c arrays c-preprocessor

以下代码段:

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数组的数据,但有几个C预处理器中的其他const数组依赖于它们比(比方说)为每个源数组的每个元素定义预处理器宏更清晰吗?

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

2 个答案:

答案 0 :(得分: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 };

答案 1 :(得分:0)

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

#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视为单个参数。