【问题标题】:How to remove the warning in gcc 4.6: missing initializer [-Wmissing-field-initializers]?如何删除 gcc 4.6 中的警告:缺少初始化程序 [-Wmissing-field-initializers]?
【发布时间】:2012-11-02 15:30:52
【问题描述】:

代码:

  GValue value = { 0 };

给出以下警告:

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

我知道那是gcc's BUG;但是有什么技巧可以删除它吗?看到这样不真实的警告真的不太好。但我不想关闭警告,因为它也会对我隐藏真正的警告。很抱歉,但我还不能将我的 gcc 更新到 4.7(看起来已经修复)版本。

【问题讨论】:

  • 我非常怀疑这是一个 gcc 错误。你能告诉我们GValue的结构定义吗?
  • 这只是一个例子;我正在寻找适用于任何结构的解决方案。
  • @GajananH 我认为我们可以假设它是一个 GLib GValue——这意味着它有多个成员(实际上,值得的结构 没有一个成员?)
  • @hobbs:与结构体有多少成员无关,通过使用{0},所有成员都应设置为0。正如您在我帖子中的链接中看到的那样,它在 C 标准中进行了描述。
  • 没有错误。根据该标准,符合标准的实现可以出于任何原因(包括外观原因)发出诊断消息,只要它仍然接受有效程序(即它是警告而不是错误)。您可以禁用此特定警告。

标签: c gcc struct warnings glib


【解决方案1】:

你可以使用:

-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】:

    使用G_VALUE_INIT初始化GValue-s。他们的(私有)结构在/usr/include/glib-2.0/gobject/gvalue.h 中,其中#define G_VALUE_INIT 适当。

    我强烈不同意您认为这是 GCC 错误的评估。如果字段未使用-Wmissing-field-initializers 显式初始化,您会要求收到警告,并且您会收到应得的警告。

    遗憾的是,G_VALUE_INIT 没有记录,但它就在这里。代码与

    GValue value = G_VALUE_INIT;
    

    如果询问-Wmissing-field-initializers,则没有通用的解决方案永远不会收到有关缺少字段初始化的警告。当您要求这样的警告时,您需要编译器警告每个不完整的初始化程序。实际上,该标准要求将所有未显式初始化的 struct 字段归零,并且 gcc 遵守该标准。

    你可以使用diagnostic pragmas

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

    但我的感觉是,您应该谨慎编码,并明确初始化所有字段。您收到的警告更像是编码风格的警告(也许您忘记了一个字段!)而不是错误警告。

    我还认为,对于您自己的(公共)struct,您应该为#define 一个初始化宏,如果打算初始化这样的struct

    【讨论】:

    • “我非常不同意你认为这是 GCC 的错误” - 同意。更进一步,初始化所有内容并让优化器丢弃虚假负载。跟踪这类错误已经过时了,因为程序员试图变得聪明(而且内存管理器没有提供一个被归零的页面)。
    • 但它一个错误。 {0} 是所谓的“通用零初始化器”,当一个人使用它时,一个是显式将所有字段初始化为它们的逻辑零。因此,GCC(或 Clang,或任何其他编译器)在这种情况下发出这样的警告是没有意义的。
    • @pwseo 旧帖,但您的说法不正确。 C 语言{0} 视为特例。没有“通用零初始化器”之类的东西,{0} 也不是一种显式初始化整个数组/结构的方法。 {0} 只是意味着:将第一个元素初始化为零,然后让所有其他成员初始化,就像它们具有静态存储持续时间一样,这是隐式完成的。这就是为什么{1} 只将第一个元素初始化为 1,其余元素初始化为零,它的工作原理完全相同。
    • @Lundin 确实,{0} 不是“通用零初始化器”,但{} 是“通用初始化器”,按照标准,它总是 对于没有用户定义的初始化程序/没有构造函数的字段,用 0 填充结构。这种语言工具经常被使用,因为 0 是程序员通常想要的。很多时候,这与(显然)没有初始化程序的 C 结构一起使用,并且不可能添加初始化程序。该警告是一个(非常烦人的)GCC 错误。为什么要添加不必要的、无用的约束来分散程序员对实际内容的注意力?
    • 您可以使用{0,}(注意逗号)将所有字段初始化为零,但它会阻塞某些结构布局。这与 C 接近“通用零初始化器”一样接近。如果你真的想要一个通用的零初始化器,请在结构实例上使用memset()
    【解决方案3】:

    似乎也使用了.field风格的初始化,比如:

    GValue value = { .somefield = 0 };
    

    将导致编译器不发出警告。不幸的是,如果结构是不透明的,那么这是一个非首发。

    【讨论】:

    • 对于最近的 gcc 版本,这可能不再正确(我在不同的代码库上看到了相同的警告,使用指定的初始化程序,如您所示,使用 arm-gcc 8)。
    • 有趣。 IIRC C 标准要求使用此构造将所有未命名字段初始化为零值。所以没有未初始化的字段。
    • 我相信它确实零初始化,只是警告缺少显式初始化程序。此外,似乎这个警告只发生在 C++,而不是 C 代码。另见gcc.gnu.org/bugzilla/show_bug.cgi?id=39589
    猜你喜欢
    • 2014-03-06
    • 2021-04-27
    • 1970-01-01
    • 1970-01-01
    • 2018-05-23
    • 2014-07-30
    • 2012-11-24
    • 1970-01-01
    • 2014-04-07
    相关资源
    最近更新 更多