【问题标题】:Why do I get "warning: missing initializer for member"? [-Wmissing-field-initializers]为什么我会收到“警告:缺少成员的初始化程序”? [-Wmissing-field-initializers]
【发布时间】:2014-03-06 16:18:01
【问题描述】:

我想知道为什么在一种情况下我收到有关初始化的警告,而在另一种情况下却没有。代码位于 C++ 源文件中,并使用 GCC 4.7 和 -std=c++11


struct sigaction old_handler, new_handler;

上面会产生 NO 警告,带有 -Wall-Wextra


struct sigaction old_handler={}, new_handler={};
struct sigaction old_handler={0}, new_handler={0};

以上会产生警告:

warning: missing initializer for member ‘sigaction::__sigaction_handler’ [-Wmissing-field-initializers]
warning: missing initializer for member ‘sigaction::sa_mask’ [-Wmissing-field-initializers]
warning: missing initializer for member ‘sigaction::sa_flags’ [-Wmissing-field-initializers]
warning: missing initializer for member ‘sigaction::sa_restorer’ [-Wmissing-field-initializers]

我已经阅读了How should I properly initialize a C struct from C++?Why is the compiler throwing this warning: "missing initializer"? Isn't the structure initialized? 以及像http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750 这样的错误报告。我不明白为什么未初始化的结构 生成警告,而初始化的结构 生成警告。

为什么未初始化的结构不生成警告;为什么初始化的结构正在生成一个警告?

【问题讨论】:

标签: c++11 gcc initialization compiler-warnings member


【解决方案1】:

当您初始化结构时,编译器会警告所有成员都未初始化。声明一个未初始化的结构没有什么需要警告的。当您(部分)初始化未初始化的结构时,您应该会收到相同的警告。

struct sigaction old_handler, new_handler;
old_handler = {};
new_handler = {};

所以,这就是区别。您的不产生警告的代码根本不是初始化。为什么 gcc 警告零初始化结构完全超出了我的范围。

【讨论】:

    【解决方案2】:

    这是一个有缺陷的警告。您确实初始化了所有成员,只是没有每个成员的初始化程序分别出现在代码中。

    如果您知道自己在做什么,请忽略该警告。我也经常收到这样的警告,而且我经常心烦意乱。但我无能为力,只能忽略它。

    为什么未初始化的结构没有给出警告?我不知道,但很可能是因为你没有尝试初始化任何东西。所以 GCC 没有理由相信你在初始化时犯了错误。

    【讨论】:

      【解决方案3】:

      这是一个简单的例子:

      #include <iostream>
      
      struct S {
        int a;
        int b;
      };
      
      int main() {
        S s { 1 }; // b will be automatically set to 0
                   // and that's probably(?) not what you want
        std::cout<<"s.a = "<<s.a<<", s.b = "<<s.b<<std::endl;
      }
      

      它给出警告:

      missing.cpp:在函数“int main()”中:
      missing.cpp:9:11:警告:缺少成员“S::b”的初始化程序 [-Wmissing-field-initializers]

      程序打印:

      s.a = 1,s.b = 0

      警告只是来自编译器的提醒,S 有两个成员,但您只显式初始化其中一个,另一个将设置为零。如果这是您想要的,您可以放心地忽略该警告。

      在这样一个简单的例子中,它看起来很傻很烦人;如果您的结构有很多成员,那么此警告可能会有所帮助(捕捉错误:错误计算字段数或拼写错误)。


      为什么未初始化的结构没有产生警告?

      我猜它只会产生太多警告。毕竟这是合法的,如果你使用未初始化的成员,它只是一个错误。例如:

      int main() {
        S s;
        std::cout<<"s.a = "<<s.a<<", s.b = "<<s.b<<std::endl;
      }
      

      missing.cpp:在函数“int main()”中:
      missing.cpp:10:43: 警告:“s.S::b”在此函数中未初始化 [-Wuninitialized]
      missing.cpp:10:26: 警告:'s.S::a' 在此函数中未初始化 [-Wuninitialized]

      尽管它没有警告我 s 的未初始化成员,但它确实警告我使用未初始化的字段。一切都很好。

      为什么初始化的结构会产生警告?

      仅当您明确但部分初始化字段时,它才会警告您。提醒一下,该结构的字段比您枚举的要多。在我看来,这个警告的有用性值得怀疑:它确实会产生太多的误报。好吧,默认情况下它没有打开是有原因的......

      【讨论】:

        【解决方案4】:

        防止该警告(或错误,如果您或您的组织将警告视为错误(-Werror 选项))的唯一方法是将memset() 设置为初始值。例如:

        #include <stdio.h>
        #include <memory.h>
        
        typedef struct {
            int a;
            int b;
            char c[12];
        } testtype_t;
        
        int main(int argc, char* argv[]) {
            testtype_t type1;
        
            memset(&type1, 0, sizeof(testtype_t));
        
            printf("%d, %s, %d\n", argc, argv[0], type1.a);
            return 0;
        }
        

        然而,对于 GCC 维护者来说,这似乎不是很干净,初始化结构的方法只有一种,而且代码美不在他们的列表之首。

        【讨论】:

        【解决方案5】:

        您正在解决症状,但没有解决问题。根据我在第 10.15 节中的“UNIX 环境中的高级编程,第二版”的副本:

        请注意,我们必须使用 sigemptyset() 来初始化结构的 sa_mask 成员。我们不保证 act.sa_mask = 0 做同样的事情。

        所以,是的,您可以使警告静音,不,这不是您初始化 struct sigaction 的方式。

        【讨论】:

        • 谢谢,这是有道理的。我可能正在分裂 C++ 头发,但调用 sigemptysetnot C++ 人使用的初始化。通常C++中的说法是“赋值不是初始化”,但我认为sigemptyset的我们是类似的。
        猜你喜欢
        • 2012-11-02
        • 2021-04-27
        • 2018-05-23
        • 2012-12-16
        • 1970-01-01
        • 2018-11-24
        • 2010-12-05
        • 2011-01-16
        • 1970-01-01
        相关资源
        最近更新 更多