C中的编译时查找表(C11)

Ste*_*oyd 5 c arrays c11

我想知道C是否具有语言或编译器(gcc)中的功能,以允许我将const的初始化数组转换为const结构的编译时查找表.这是我的情况改造:

typedef struct Entry {
    bool alive;
    float a, b, c;
    double d, e, f;
} Entry;
Run Code Online (Sandbox Code Playgroud)

现在,我有一个数组的声明:

extern const int entryCount; // Assume this is equal to an enum value.
extern const Entry entries[entryCount];
Run Code Online (Sandbox Code Playgroud)

如上所述,数组中的位置相对于枚举常量,该常量是放入入口结构的数据的特征.假设entryCount初始化为枚举中的条目数.这是我的问题所在,当我初始化这个数组时:

const int entryCount = ENTRY_COUNT;
const Entry entries[entryCount] = {
    { false, 0.1f, 0.2f, 0.0f, 1.0, 1.0, -1.0 },
    ...
};
Run Code Online (Sandbox Code Playgroud)

它们是在编译时创建的,并且在运行时不会产生任何开销吗?或者它是否在运行时分配在内存中?因为价值永远不会改变.我怎样才能在C中实现这一目标?

Jen*_*edt 3

如果定义数组所需的所有组件都是 C 标准意义上的编译时常量,则可以实现您想要的效果。唯一不是你所给予的就是entryCount。它确实必须是一个enum常数。

然后你必须将该数组作为全局(文件范围)数组。如果您想通过包含文件 (.h) 在不同的 .c 文件(所谓的编译单元)中包含相同的数组,则必须声明它static,这样在链接程序时多个定义就不会发生冲突。

enum { entryCount = ENTRY_COUNT };
static const Entry entries[entryCount] = {
    { false, 0.1f, 0.2f, 0.0f, 1.0, 1.0, -1.0 },
    ...
};
Run Code Online (Sandbox Code Playgroud)

static这里意味着这将创建一个变量,该变量的生命周期跨越程序的整个执行过程,但不会生成该变量的外部符号。如果您将#include相同的变量定义放入多个 .c 文件中,则这是必要的。

这没有运行时开销,也没有对条目的访问,例如entries[4].d现在应该由良好的优化编译器优化掉的条目。

这只有一个缺点,因为它会在所有单元中重复生成数组,即使那里不需要它。避免这种情况的一种方法是将宏扩展为像这样的复合文字

#define ENTRIES (const Entry [entryCount]){        \
    { false, 0.1f, 0.2f, 0.0f, 1.0, 1.0, -1.0 },   \
    ...                                            \
}
Run Code Online (Sandbox Code Playgroud)

const给编译器留下了余地,只分配该数组一次(如果有的话),并且将避免在根本不使用该功能的编译单元中进行额外的复制。