2014-02-09 2 views
5

Мне интересно, почему я получаю предупреждение об инициализации в одном случае, но не в другом. Код находится в исходном файле на C++ и с использованием GCC 4.7 с -std=c++11.Почему я получаю предупреждение: отсутствует инициализатор для члена? [-Wmissing-field-initializers]


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?, и сообщения об ошибках, как http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750. Я не понимаю, почему неинициализированная структура не генерирует предупреждение, а инициализированная структура - это, генерирующая предупреждение.

Почему неинициализированные структуры не создает предупреждение; и почему инициализированные структуры генерируют предупреждение?

+0

То, что вы называете инициализированным, только частично инициализировано, поэтому предупреждение. –

ответ

7

Вот простой пример:

#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 основной()»:
отсутствует.CPP: 9: 11: предупреждение: отсутствует инициализатор для члена 'S' :: б [-Wmissing-полевые инициализаторы]

Программа печатает:

са = 1, SB = 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: предупреждение: 'Ss :: б' используется неинициализированным в этой функции [ -Wuninitialized]
missing.cpp: 10: 26: предупреждение: 'Ss :: а' используется неинициализированным в этой функции [-Wuninitialized]

несмотря на то, что не предупредил меня о неинициализированных членах s , он предупредил меня об использовании неинициализированных полей. Все хорошо.

Почему инициализированные структуры генерируют предупреждение?

Он предупреждает вас, если вы явно, но частично инициализации полей. Это напоминание о том, что структура имеет больше полей, чем вы перечислили. На мой взгляд, сомнительно, насколько полезно это предупреждение: оно действительно может вызвать слишком много ложных тревог. Ну, это не по умолчанию по какой-то причине ...

2

Компилятор предупреждает, что все элементы не инициализируются при инициализации структуры. Нечего предупреждать об объявлении неинициализированной структуры. Вы должны получать те же предупреждения, когда вы (частично) инициализируете неинициализированные структуры.

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

Так вот в чем разница. Ваш код, который не создает предупреждение, вовсе не является инициализацией. Почему gcc предупреждает о нулевой инициализированной структуре вообще, вне меня.

3

Это неисправное предупреждение. Вы выполнили инициализацию всех членов, у вас просто не было инициализаторов для каждого члена, отдельно отображаемого в коде.

Просто игнорируйте это предупреждение, если вы знаете, что делаете. Я регулярно получаю такие предупреждения, и я регулярно расстраиваюсь. Но я ничего не могу с этим поделать, но игнорировать его.

Почему неинициализированная структура не дает предупреждения? Я не знаю, но, скорее всего, это потому, что вы ничего не пытались инициализировать. Поэтому у GCC нет оснований полагать, что вы допустили ошибку при выполнении инициализации.

1

Единственный способ предотвратить это предупреждение (или ошибку, если вы или ваша организация обрабатываете предупреждение как ошибку (опция -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 сопровождающим, есть только один способ инициализировать структура и код красоты не стоит на вершине их списка.

+0

memset может быть ошибочным в некоторых случаях, см. Http://stackoverflow.com/questions/2837854/initializing-an-object-to-all-zeroes –

1

Вы решаете симптом, но не проблема. По моей копии «Расширенное программирование в среде UNIX, второе издание» в разделе 10.15:

Обратите внимание, что мы должны использовать sigemptyset() для инициализации члена sa_mask структуры. Мы не гарантируем, что act.sa_mask = 0 делает то же самое.

Итак, да, вы можете отключить предупреждение, и это не так, как вы инициализируете структуру sigaction.

+0

Спасибо, это имеет смысл. Я, вероятно, раскалываю C++-волоски, но вызов 'sigemptyset' - это * не * инициализация, используемая людьми C++. Обычно высказывание: «Назначение не инициализация» на C++, но я думаю, что «sigemptyset» аналогичен. – jww

 Смежные вопросы

  • Нет связанных вопросов^_^