如何在GCC 4.6中消除警告:“missing initializer [-Wmissing-field-initializers]”?

9
代码
  GValue value = { 0 };

会出现以下警告:

缺少初始化程序[-Wmissing-field-initializers]

我知道这是一个 GCC bug,但是有没有什么诀窍可以解决它?看到这种不真实的警告真的很不好。但是我不想关闭警告,因为它也会隐藏真正的警告。对不起,我还不能将GCC升级到4.7(在那里似乎已经修复),所以只能暂时忍受。


3
我很怀疑这是gcc的错误。你能否展示一下GValue的结构定义? - CCoder
这只是一个例子,我正在寻找适用于任何结构的解决方案。 - Jack
@GajananH 我认为我们可以假设它是一个 GLib GValue —— 这意味着它有不止一个成员(的确,什么值得的 struct * 没有多个成员?) - hobbs
@hobbs: 独立于结构体中有多少成员,使用 {0} 将会把所有成员都设置为 0。正如您在我的帖子中所看到的,这是在 C 标准中描述的。 - Jack
5
没有错误。根据标准,符合规范的实现可以出于任何原因发出诊断消息,包括纯粹的外观原因,只要它仍然接受有效的程序(即它是一个警告而不是错误)。您可以禁用此特定警告。 - n. m.
也许我有点挑剔,但你是在编译哪个版本的C或C++呢?在某些情况下,这可能是一个有效的警告,比如C89(还有人在使用吗?) - jww
3个回答

11

使用 G_VALUE_INIT 来初始化 GValue。它们的(私有)结构在 /usr/include/glib-2.0/gobject/gvalue.h 中,其中通过 #define G_VALUE_INIT 适当地定义。

我强烈反对你的评估认为这是GCC的错误。您需要使用 -Wmissing-field-initializers 显式地初始化字段,并且您会得到应有的警告。

遗憾的是,虽然没有文档,但是 G_VALUE_INIT 在这里。代码如下:

GValue value = G_VALUE_INIT;

如果要求编译器发出每个不完整初始化的警告,那么就没有一种万无一失的方法来避免缺少字段初始化的警告。实际上,标准要求所有未明确初始化的结构体字段都被清零,而 gcc 遵循该标准。您可以使用类似诊断指示语句的方式。

#pragma GCC diagnostic ignored "-Wmissing-field-initializers"

但我的感觉是你应该仔细编码,并显式初始化所有字段。你得到的警告更多是一种编码风格警告(也许你忘记了一个字段!)而不是一个错误警告。

我还相信,对于你自己(公共)的struct,如果这样的struct被预期要初始化,那么你应该#define一个初始化宏。


8
但这确实是一个Bug。"{0}"被称为"通用零初始化器",当使用它时,就是在明确地将所有字段初始化为它们的逻辑零。因此,对于GCC(或Clang或任何其他编译器)在这些情况下发出警告是没有意义的。 - pwseo
5
@pwseo 老帖子了,但是你的说法是不正确的。C语言并没有将{0}视为特殊情况。也不存在所谓的“通用零初始化器”,{0}也不是一种显式地初始化整个数组/结构体的方法。{0}仅仅意味着:_将第一个元素初始化为零,然后让每个其他成员隐式地按照静态存储期进行初始化_。这就是为什么{1}只将第一个元素初始化为1,其余的都是零,因为它的工作方式完全相同。 - Lundin
5
@Lundin,确实,“{0}”不是“通用零初始化器”,但“{}”是“通用初始化器”,根据标准,它将始终为没有用户定义初始化程序/构造函数的字段填充结构体中的值为0。这种语言功能经常被使用,因为程序员通常想要的就是0。很多时候,这被用于没有初始化器(显然)且无法添加初始化器的C结构体。这个警告是GCC的一个(非常烦人的)bug。为什么要添加不需要的、不有用的约束条件,让程序员分心呢? - aberaud
1
@aberaud 嗯?在C语言中不允许使用空的初始化列表,请参考C11 6.7.9或阅读这里。此外,在C语言中不存在构造函数,因此无需关注此问题。 - Lundin
2
你可以使用{0,}(注意逗号)将所有字段初始化为零,但它会卡在某些结构体布局上。这是C语言能够接近的“万能零初始化器”。如果你真的需要一个万能的零初始化器,在结构体实例上使用memset()函数。 - Philip Withnall
显示剩余2条评论

11

你可以使用:

-Wno-missing-field-initializers

要特别禁止该警告。相反,您可以使用以下方式将其变成错误:

-Werror=missing-field-initializers

这两个选项都可以与GCC 4.7.1兼容;我认为它们也可以与GCC 4.6.x兼容,但它们不能与所有早期版本的GCC兼容(GCC 4.1.2可以识别-Wno-missing-field-initializers,但无法识别-Werror=missing-field-intializers)。

显然,抑制警告的另一种方法是显式初始化所有字段。不过那可能很麻烦。


2
似乎使用.field-style初始化方法,例如:
GValue value = { .somefield = 0 };

这将导致编译器不发出警告。但如果结构体是不透明的,这是不可行的。


最近的gcc版本可能不再适用(我曾在另一个使用指定初始化程序的代码库上看到相同的警告,使用arm-gcc 8)。 - Matthijs Kooijman
有趣。如果我没记错的话,C标准要求使用这种结构初始化所有未命名字段为它们的零值。因此,没有未初始化的字段。 - John Hascall
我相信它确实会进行零初始化,只是警告缺少显式初始化程序。此外,似乎这个警告只会在C++代码中出现,而不会在C代码中出现。详见https://gcc.gnu.org/bugzilla/show_bug.cgi?id=39589。 - Matthijs Kooijman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接