gcc 为什么我会得到“警告:缺少成员”“的初始值设定项?[-Wmissing-field-initializers]?

j91ykkif  于 2022-11-13  发布在  其他
关注(0)|答案(5)|浏览(730)

为什么在一种情况下我会得到关于初始化的警告,而在另一种情况下却没有呢?代码在C++源文件中,我使用的是GCC 4. 7和-std=c++11

struct sigaction old_handler, new_handler;

以上代码不会对-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? * 和 * Bug 36750. Summary: -Wmissing-field-initializers relaxation request * 等错误报告。我不明白为什么未初始化的struct * 没有 * 生成警告,而初始化的struct * 却 * 生成警告。
为什么未初始化的structs * 不生成 * 警告;为什么初始化的structs * 生成 * 警告?

p5cysglq

p5cysglq1#

下面是一个简单的例子:

#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()'中:
失踪。cpp:9:11:警告:缺少成员“S::b”的初始值设定项[-Wmissing-field-initializers]
程序将打印:
s. a = 1,s.B = 0

这个警告只是编译器的一个提醒,提醒您S有两个成员,但您只明确初始化其中一个,另一个会设定为零。如果您想要这样做,可以放心地忽略这个警告。

在这样一个简单的例子中,它看起来愚蠢而令人讨厌;如果你的结构体有很多成员,那么这个警告会很有帮助(捕捉错误:错误地计算字段或打字错误的数目)。
为什么未初始化的结构体不生成警告?

**我猜它只会产生太多的警告。**毕竟,它是法律的的,只有当您使用未初始化的成员时,它才是一个bug。例如:

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

missing.cpp:在函数'int main()'中:
失踪。cpp:10:43:警告:在此函数中使用了未初始化的“s.S::B”[-Wuninitialized]
失踪。cpp:10:26:警告:在此函数中使用了未初始化的“s.S::a”[-Wuninitialized]
尽管它没有警告我s的未初始化成员,但它警告我使用未初始化字段。一切都很好。
为什么初始化的结构会产生警告?
只有当你显式但 * 部分 * 初始化字段时,它才会警告你。它提醒你结构体的字段比你枚举的字段多。在我看来,这个警告的有用性值得怀疑:它确实会产生太多的假警报。嗯,它默认不开是有原因的...

sg24os4d

sg24os4d2#

这是一个有缺陷的警告。你确实初始化了所有的成员,但是你只是没有让每个成员的初始化器分别出现在代码中。
如果你知道自己在做什么,就忽略这个警告。我也经常收到这样的警告,我经常感到不安。但我对此无能为力,只能忽略它。
为什么未初始化的struct没有给出警告呢?我不知道,但很可能是因为你没有尝试初始化任何东西。所以GCC没有理由相信你在初始化时犯了错误。

but5z9lq

but5z9lq3#

您解决的是症状,而不是问题。根据我在第10.15节中的 Advanced Programming in the UNIX Environment, Second Edition
注意,我们必须使用sigemptyset()来初始化结构的 sa_mask 成员,我们不能保证 act.sa_mask = 0 也能做同样的事情。
所以,是的,你可以把警告静音,不,这不是你初始化一个结构体sigaction的方式。

8xiog9wr

8xiog9wr4#

编译器会在您初始化结构时警告所有成员都未初始化。宣告未初始化的结构时没有任何警告。当您(部分)初始化未初始化的结构时,应该会收到相同的警告。

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

所以,这就是区别。没有产生警告的代码根本不是一个初始化。为什么gcc会对零初始化的结构发出警告,我不明白。

z8dt9xmd

z8dt9xmd5#

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

#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维护者来说,只有一种方法来初始化一个结构体,而代码美并不在他们的列表之首。

相关问题