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

时间:2018-07-10 16:58:26

标签: c gcc c99

如果某个明确初始化的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]);
    }
}

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

我可以在my_enum_names的定义中添加某种杂注或属性,以便如果其大小不等于MY_ENUM_COUNT时,编译器将引发警告或错误? strong>

一些说明:

  • 我专门指的是显式初始化的数组,这意味着它们的大小在编译时就知道了。
  • 我特指GCC编译器,包括编译器扩展。

我发誓我以前可能已经使用过GCC的__attribute__扩展程序之一,但是现在我找不到任何符合我想要功能的文档。

2 个答案:

答案 0 :(得分:3)

_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];

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

答案 1 :(得分:0)

怎么样

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

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

此外,通过上述操作,如果删除枚举,则如果您忘记更新数组初始化,则编译器将警告您许多初始化方法。