【问题标题】:Is it wise to ignore gcc/clang's "-Wmissing-braces" warning?忽略 gcc/clang 的“-Wmissing-braces”警告是否明智?
【发布时间】:2012-12-16 20:31:32
【问题描述】:

考虑以下程序:

#include <array>

int main()
{
  std::array<int, 1> x = { 0 }; // warning!
  x = { { 0 } }; // no warning
  return 0;
}

第一次初始化导致 gcc 4.7.2 上的警告...

main.cpp:5:22: warning: unused variable ‘x’ [-Wunused-variable]

...和clang 3.1

main.cpp:5:28: warning: suggest braces around initialization of subobject [-Wmissing-braces]
  std::array<int, 1> x = { 0 };

就标准而言,双花括号和单花括号之间应该没有区别,至少在这个例子中是这样。

警告有两种处理方式:

  1. 关掉就行了
  2. 修复代码,让编译器开心

你有什么建议?恕我直言,双卷曲的表情看起来有些难看。另一方面,警告可能会在更复杂的示例中检测到真正的问题。您知道警告可以帮助您的示例吗?

【问题讨论】:

标签: c++ c++11 compiler-warnings


【解决方案1】:

-Wmissing-braces will no longer be enabled in GCC's -Wall (for C++ mode), as of 4.8, for precisely the reason you describe. 对于当前版本的 GCC,禁用或忽略警告,您拥有的代码将按照应有的方式编写。

警告可能是为了涵盖诸如

之类的代码
struct A { int a; int b; };
struct B { A a; int b; };
B b = {
  1,
  2 // initialises b.a.b, not b.b
};

但是,恕我直言,-Wmissing-field-initializers 已经处理得很好,它不会警告您的原始代码。

【讨论】:

  • 该警告至少涵盖了人们应该写int x[2][2] = {0}而应该写{{0}}的C案例。
  • @jørgensen 他们为什么要这样做?在 C 中,{0} 是适用于所有类型的初始值设定项,因此使用起来超出了严格必要的范围。它完全有效,它的意思很明显,那为什么要引起警告呢?
  • Clang 仍然警告这个问题,但有一个类似的错误打开,请参阅llvm.org/bugs/show_bug.cgi?id=21629
  • 您能否澄清您的评论“初始化 b.a.b,而不是 b.b”。我的意思是,语句B b = {1, 2}b.a.a 初始化为1b.a.b 初始化为2b.b 初始化为0b.b 的初始化归因于 C11, 6.7.9 (21)(即“[..],聚合的其余部分应隐式初始化,与具有静态存储持续时间的对象相同。”)。因此,在该示例中,所有内容都已初始化。
  • @maxschlepzig 我的意思是要将评论应用于2。这样更清楚吗?
【解决方案2】:

我在 Xcode 6.1.1(截至 2015 年 3 月 9 日的当前版本)中收到相同的警告。当我在每个子对象周围添加额外的大括号时,我得到一个错误。当我在整个初始化列表周围添加一组额外的大括号时,警告就会消失。根据标准规范 14882:2011 23.3.2.1 [array.overview] subsection 2 明确规定

array<T, N> a = { initializer-list };

其中 initializer-list 是一个逗号分隔的列表,最多包含 N 个元素 其类型可转换为 T

Xcode 6.1.1 中的代码结果(下)

array<int, 2> key1 = {1, 2}; // warning: suggest braces around initialization of subobject

array<int, 2> key2 = { {1}, {2} }; // error: no viable overload =

array<int, 2> key3 = array<int, 2> { {1}, {2} }; // error: excess elements in struct initializer

array<int, 2> key4 = { {1, 2} }; // no warning and no error

当我们查看 14882:2011 8.5 [dcl.init] 第 1 小节时,我们看到“初始化器列表”可以选择包含“初始化器子句”,它本身可以是“支撑初始化器列表”。所以无论哪种方式都应该是正确的。虽然根据规范,我个人认为单括号不应该为 std::array 初始化器列表输出编译器警告,而双括号是多余的。

【讨论】:

    【解决方案3】:

    Clang 6.0 取消了关于缺少大括号的警告。 svn 日志说:

    当聚合初始化具有单个字段的结构时,抑制 -Wmissing-braces 警告,该字段本身就是聚合。在 C++ 中,std::array 类型的这种初始化保证按照标准工作,是完全惯用的,并且“建议”的替代方案来自 Clang 在技术上是无效的。

    所以如果需要支持,我会省略大括号并为 6.0 之前的 Clang 禁用 -Wmissing-braces

    【讨论】:

    【解决方案4】:

    当使用 -Wno-missing-braces 忽略 Clang 警告时,我建议启用 -Wmissing-field-initializers(或使用 -Wextra,其中也包含它)。否则,您会错过一个有用的警告,如本例所示:

    #include <cstdio>
    
    struct A
    {
      int i;
      int arr[2];
      int j;
    };
    
    void print(const A& a)
    {
      printf("i=%d, arr={%d,%d}, j=%d\n", a.i, a.arr[0], a.arr[1], a.j);
    }
    
    int main() {
      A a = {1, 2, 3}; // this is the critical line
      print(a); // output: i=1, arr={2,3}, j=0
    
      A b = {1, {2}, 3};
      print(b); // output: i=1, arr={2,0}, j=3
    
      A c = {1, {2,0}, 3};
      print(c); // output: i=1, arr={2,0}, j=3
    
      return 0;
    }
    
    $ clang++ -Wall example.cpp
    example.cpp:16:13: warning: suggest braces around initialization of
          subobject [-Wmissing-braces]
      A a = {1, 2, 3};
                ^~~~
                {   }
    1 warning generated.
    
    $ clang++ -Wall -Wno-missing-braces example.cpp
    (no warnings)
    
    $ clang++ -Wall -Wno-missing-braces -Wmissing-field-initializers example.cpp
    example.cpp:16:17: warning: missing field 'j' initializer
          [-Wmissing-field-initializers]
      A a = {1, 2, 3};
                    ^
    1 warning generated.
    
    $ clang++ --version
    clang version 3.8.1 (tags/RELEASE_381/final)
    

    作为比较,这是 GCC 所做的:

    $ g++ -Wall -Wextra example.cpp
    (no warning)
    
    $ g++ -Wall -Wmissing-field-initializers example.cpp
    example.cpp: In function ‘int main()’
    example.cpp:16:17: warning: missing initializer for member ‘A::j’ [-Wmissing-field-initializers]
       A a = {1, 2, 3};
                     ^
    

    总结:

    • 对于 Clang,我建议 -Wno-missing-braces -Wmissing-field-initializers 在不丢失其他有用警告的情况下使警告静音
    • GCC 在原始std::array&lt;int, 1&gt; x = { 0 }; 示例中没有抱怨,因此无需禁用任何警告。但是,我建议启用-Wmissing-field-initializers(或使用-Wextra),因为-Wall 没有启用它。

    【讨论】:

    • 你可以使用-Wno-missing-braces-Wall 吗? IE。 “除了没有缺失的大括号之外的所有内容”?
    • @DavidDoria 是的,你可以
    猜你喜欢
    • 1970-01-01
    • 2017-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多