2011-01-24 6 views
7

У меня есть следующий код в файле C++:Как правильно инициализировать C-структуру из C++?

#include <sys/socket.h> 

// ... 
void someFunc() { 
    struct msghdr msg = {0}; // <<< Uninitialized member here 
} 

Когда я компилирую с g++ помощью -Wall -Wextra, я получаю предупреждения:

error: missing initializer for member 'msghdr::msg_namelen' 
...same for several other fields 

Моя проблема заключается в следующем: я не могу явно инициализировать все поля, потому что я не знаю, какие поля будут существовать (кросс-платформенная) в struct msghdr. Структура не имеет конструктора по умолчанию, так как это структура C. У меня создалось впечатление, что форма = {0} привела к нулевой инициализации всех полей (что было бы хорошо для меня), но сообщение об ошибке g++ не предполагает.

Какие у меня варианты?

+0

Возможный дубликат [Почему компилятор бросает это предупреждение: «Отсутствует инициализатор»? Не инициализирована ли структура?] (Http://stackoverflow.com/questions/1538943/why-is-the-compiler-throwing-this-warning-missing-initializer-isnt-the-stru) – ergosys

ответ

8
void someFunc() 
{ 
    msghdr msg = {}; // <<< All members zero-initialized 
} 

Г ++ -Wextra уровень предупреждения ИМХО не очень полезно.

Код, который у вас есть, также официально одобрен для «C struct», в стандартах, известных как POD (Обычные старые данные). Но ваш код явно инициализирует первый член с 0. Это не обязательно будет работать для агрегата, который не является POD, например. с std::string в качестве первого члена, в то время как чистый {} будет работать и для этого.

Попутно, часто POD, как тот, с которым вы имеете дело, имеет байтовый счет в качестве первого члена, а затем вы можете делать как & hellip;

void foo() 
{ 
    SomePODStruct o = {sizeof(o)}; // The other members zero-initialized. 
} 

Возможно добавить STATIC_ASSERT, что элемент количество байт является первым (по смещению 0).

Приветствия & НТН,

+1

Я не согласен с предложением _ Уровень предупреждения g ++ -Wextra не очень полезен. – peoro

+1

@peoro: OK. Я добавил «ИМХО».:-) –

+0

Спасибо за ввод Alf, хорошо знать, что это '-Wextra' сломано, а не мое понимание C++ :-) –

4

Это должно работать:

memset(&msg, 0, sizeof(msg)); 
+0

исправить вашу опечатку и Я уберу свой ответ, вы избили меня до секунды! :) – Nim

1

Если вы не можете жить с предупреждением и/или не хотите, чтобы отключить предупреждение, то я думаю, что придется быть явной инициализацией с помощью, например, MemSet:

memset(&msg, 0, sizeof(msg)); 
0

может быть, если вы не хотите использовать конструктор по умолчанию, вы можете просто использовать функции препроцессора, как:.

#ifdef LINUX 
//init for linux 
#endif 

#ifdef WINDOWS 
//init for windows 
#endif 

и так далее

+0

Прошу прощения, я не понимаю, как это будет инициализировать структуру. Определение структуры вне моего контроля (находится в 'socket.h'). Можете ли вы привести пример того, как будет выглядеть инициализация структуры в предлагаемом решении? –

+0

Я имел в виду, что вы знаете, как структура ищет каждую платформу. И вы можете инициализировать его для каждой платформы, потому что знаете все поля. Так что если где-нибудь в приложении вы напишите, например, #define LINUX, то #ifdef часть LINUX будет добавлена ​​препроцессором к коду и будет выполнена. В этом случае вы будете отличаться для разных платформ. http://stackoverflow.com/questions/2989810/which-cross-platform-preprocessor-defines-win32-or-win32-or-win32 - может быть полезно – Andrew

+0

ОК, это имеет смысл, спасибо за разъяснение. –

2

Конкретное предупреждение флаг что вызывает это -Wmissing-field-initializers, который включен как часть -Wextra. Поэтому самым простым способом избежать этого (фиктивного) предупреждения является использование -Wno-missing-field-initializers.

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