在我的当前项目中,我们使用MISRA 2004标准,使用三个GCC编译器版本3.2.3、4.4.2和5.4.0。
我们使用严格检查构建,包括pedantic开关、c89标准和许多其他限制。其中之一是所有数据必须在声明时初始化。
问题在于,在GCC 3.2.3上,通用的零初始化器{0}
只适用于基本单元类型的数组。如果我有一个结构体数组,那么我会得到一个缺少大括号的警告,只有当我将{0}
更改为{{0}}
时才能消除警告。
struct my_type my_thing[NUMBER_OF_THINGS] = {0};
变成。struct my_type my_thing[NUMBER_OF_THINGS] = {{0}};
但是,当处理具有结构成员的结构数组时,这种方法无法使用。这时问题出在 4.4.2 编译器上,会出现缺少初始化程序的错误。因此,我不得不这样做:
struct my_struct_with_structs_inside my_other_thing[NUMBER_OF_THINGS] = {{0, 0, {0}, 0}};
这样的代码可以通过编译器,但会触发我们的MISRA检查器,因为MISRA要求使用通用的单一{0}初始化程序或完整的整个数组初始化程序:
struct my_struct_with_structs_inside my_other_thing[NUMBER_OF_THINGS] = {{0, 0, {0}, 0},
{0, 0, {0}, 0},
{0, 0, {0}, 0},
{0, 0, {0}, 0},
{0, 0, {0}, 0}};
由于我们有各种限制,NUMBER_OF_THINGS
可能会在构建时从源代码外部自动生成并发生更改,因此这对我们来说是不切实际的。
核心问题
我想告诉我的老板所谓的通用初始化器 {0}
可以用于初始化任何数组。我发现在GCC邮件列表和Bugzilla上有很多年的帖子都认为我提到的编译器警告是错误,并且称 {0}
是标准的一部分。然而,它们中没有一个提到哪个标准,我也无法在ISO C89或C99草案或K&R v2中找到 {0}
。{0}
是标准吗? 有没有办法保证一个具有结构成员的结构体数组被初始化为全零(或NULL)?
问题在于,虽然我可以消除MISRA代码的违规情况,但我不确定这样做:
struct my_struct_with_structs_inside my_other_thing[NUMBER_OF_THINGS] = {{0, 0, {0}, 0}};
使用该函数足以确保数组完全清零。
有人能从问题的根源提供智慧吗?
{0}
在GCC 3.2.3下无法编译。如果你的代码必须在GCC 3.2.3下编译,那么无论它们有多标准化,你都不能使用那些在GCC 3.2.3下无法编译的东西。 - user2357112