我可以在编译时使用 gcc 扩展强制执行显式初始化的数组大小吗?

Can I enforce explicitly-initialized array size at compile-time with gcc extensions?

如果某个显式初始化的 C 数组中的元素数量不等于某个值,我可以强制 GCC 在编译时抛出警告或错误吗?

考虑以下简单的 C 程序:

#include <stdio.h>

enum my_enum {
    MY_ENUM_FIRST,
    MY_ENUM_SECOND,
    MY_ENUM_THIRD,
    MY_ENUM_COUNT
};

// indexable by my_enum
const char *my_enum_names[] = {
    "first",
    "second",
    "third",
};

int main(void) {
    int i;

    for (i = 0; i < MY_ENUM_COUNT; i++)
    {
        printf("%s\n", my_enum_names[i]);
    }
}

除非它们在代码中直接相邻,否则开发人员可能不会意识到枚举和数组必须彼此保持 "synchronized"。开发人员可以将条目添加到枚举而不是数组(反之亦然),因此会暴露越界漏洞。

我能否在 my_enum_names 的定义中添加某种编译指示或属性,以便如果其大小不等于 MY_ENUM_COUNT,编译器将抛出警告或错误?

一些说明:

我发誓我以前做过这件事,可能是使用 GCC 的 __attribute__ 扩展之一,但现在我找不到任何关于任何功能的文档来满足我的需求。

怎么样

const char *my_enum_names[MY_ENUM_COUNT] = { ... };

然后数组将始终包含足够的元素,但有些元素可能 NULL 然后您需要添加检查。总比冒险出界好。

另外,对于上面的内容,如果您删除了枚举,那么如果您忘记更新数组初始化,编译器将警告您关于许多初始化程序。

_Static_assert(sizeof my_enum_names / sizeof *my_enum_names == MY_ENUM_COUNT,
    "my_enum_names is the wrong size.");

在将 _Static_assert 添加到该语言之前,您可以在这些情况下使用以下声明来强制出错:

extern char my_enum_namesIsTheWrongSize[1];
extern char my_enum_namesIsTheWrongSize[sizeof my_enum_names / sizeof *my_enum_names == MY_ENUM_COUNT];

如果后者的测试为假,它会尝试声明一个元素为零的数组,这本身就是一个错误,但是,以防万一编译器不报告大小为零的数组,也会与前面的声明,因此它应该生成一条错误消息。