2012-12-16 31 views
41

Hãy xem xét các chương trình sau đây:Bạn có nên bỏ qua cảnh báo "-Wmissing-niềng răng" của gcc/clang không?

#include <array> 

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

Việc khởi đầu dẫn đến cảnh báo trên gcc 4.7.2 ...

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

... và kêu vang 3,1

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

As far như là tiêu chuẩn đi, không nên có sự khác biệt giữa các dấu ngoặc nhọn đôi hoặc đơn, ít nhất trong ví dụ này.

Có hai cách để đối phó với cảnh báo:

  1. Chỉ cần tắt nó đi
  2. Fix mã, vì vậy trình biên dịch là hạnh phúc

làm bạn đề xuất gì? IMHO, biểu hiện xoăn kép trông hơi xấu xí. Mặt khác, cảnh báo có thể phát hiện các vấn đề thực sự trong các ví dụ phức tạp hơn. Bạn có biết một ví dụ mà cảnh báo sẽ giúp bạn?

+0

Vì std :: mảng là tổng hợp. Xem [thread] [1] này. [1]: http://stackoverflow.com/questions/16341118/whats-the-correct-way-to-initialize-a-member-array-with-an-initializer-list –

+0

Chỉ cần để thông báo: để vô hiệu hóa cảnh báo này, bạn nên thêm -Wno-missing-niềng răng trên clang –

Trả lời

41

-Wmissing-braces will no longer be enabled in GCC's -Wall (for C++ mode), as of 4.8, for precisely the reason you describe. Đối với các phiên bản hiện tại của GCC, hãy vô hiệu hóa hoặc bỏ qua cảnh báo, mã bạn có được viết theo cách cần thiết.

Cảnh báo có lẽ là có nghĩa là để che mã như

struct A { int a; int b; }; 
struct B { A a; int b; }; 
B b = { 
    1, 
    2 // initialises b.a.b, not b.b 
}; 

Tuy nhiên, IMHO, mà đã được xử lý tốt đủ bởi -Wmissing-field-initializers, mà không cảnh báo về mã ban đầu của bạn.

+1

Cảnh báo được sử dụng để bao gồm ít nhất trường hợp C trong đó mọi người đã viết 'int x [2] [2] = {0}' khi họ cần phải có viết '{{0}} '. –

+7

@ jørgensen Tại sao phải không? Trong C, '{0}' là bộ khởi tạo hoạt động cho tất cả các loại và được sử dụng nhiều hơn mức cần thiết vì điều đó. Nó hoàn toàn hợp lệ, rõ ràng nó có nghĩa là gì, vậy tại sao nên gây ra một cảnh báo? – hvd

+0

Clang vẫn cảnh báo về vấn đề này, nhưng có một lỗi tương tự đang mở, hãy xem http://llvm.org/bugs/show_bug.cgi?id=21629 – usr1234567

6

Tôi nhận được cảnh báo tương tự trong Xcode 6.1.1 (phiên bản hiện tại kể từ ngày 9 tháng 3 năm 2015). Khi tôi thêm các dấu ngoặc phụ xung quanh mỗi subobject tôi nhận được một lỗi. Khi tôi thêm một bộ dấu ngoặc ôm xung quanh toàn bộ danh sách khởi tạo thì cảnh báo sẽ biến mất. Theo thông số kỹ thuật tiêu chuẩn 14882: 2011 23.3.2.1 [array.overview] tiểu mục 2 khẳng định một cách rõ ràng

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

nơi initializer-list là danh sách bằng dấu phẩy lên đến yếu tố N có loại là chuyển đổi thành T

kết quả của mã trong Xcode 6.1.1 (dưới đây)

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 

Khi chúng ta nhìn vào 14882: 2011 8,5 [dcl.init] tiểu mục 1 chúng ta thấy rằng một 'initializer-list' có thể tùy ý chứa một 'initializer-clause', mà chính nó có thể là một 'braced-init-list'. Vì vậy, một trong hai cách nên được chính xác. Mặc dù dựa trên spec tôi cá nhân nghĩ rằng niềng răng đơn không nên xuất ra một cảnh báo trình biên dịch cho một std :: array initializer-list, và đôi niềng răng là overkill.

3

Khi bỏ qua cảnh báo Clang với -Wno-missing-braces, tôi khuyên bạn nên bật -Wmissing-field-initializers (hoặc sử dụng -Wextra, cũng bao gồm nó).Nếu không, bạn bỏ lỡ một cảnh báo hữu ích như trong ví dụ này:

#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) 

Để so sánh, đây là những gì GCC làm:

$ 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}; 
       ^

Nói tóm lại:

  • Đối Clang, Tôi khuyên bạn nên -Wno-missing-braces -Wmissing-field-initializers để tắt tiếng cảnh báo mà không mất cảnh báo hữu ích khác
  • GCC không khiếu nại trong ví dụ ban đầu std::array<int, 1> x = { 0 };, vì vậy không cần phải tắt bất kỳ cảnh báo nào. Tuy nhiên, tôi khuyên bạn nên bật -Wmissing-field-initializers (hoặc sử dụng -Wextra), vì nó không được kích hoạt bởi -Wall.
+0

Bạn có thể sử dụng '-Wno-missing-niềng răng' với' -Wall' không? I E. "tất cả ngoại trừ không có thiếu-niềng răng"? –

+0

@DavidDoria Có, bạn có thể – romeric

2

Clang 6.0 sắp phát hành sẽ ngăn chặn cảnh báo về thiếu dấu ngoặc. Nhật ký svn nói:

Suppress -Wmissing-niềng răng cảnh báo khi tổng hợp-khởi tạo cấu trúc với một trường đơn lẻ là tổng hợp. Trong C++, việc khởi tạo std :: array type được đảm bảo hoạt động theo chuẩn, hoàn toàn thành ngữ, và thay thế "gợi ý" từ Clang về mặt kỹ thuật không hợp lệ.

Vì vậy, tôi sẽ bỏ qua các dấu ngoặc và tắt -Wmissing-braces cho Clang trước 6.0.

+1

Điều đó rất hữu ích. Để tham khảo, đây là nguồn của tuyên bố: https://reviews.llvm.org/rL314838 –

Các vấn đề liên quan