2011-01-24 16 views
7

Mam następujący kod w ++ pliku C:Jak poprawnie zainicjować C struct z C++?

#include <sys/socket.h> 

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

Kiedy skompilować z g++ użyciu -Wall -Wextra, dostaję ostrzeżenia:

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

Mój problem jest taki: Nie mogę jawnie zainicjować wszystko pola, ponieważ nie wiem, jakie pola będą istnieć (między platformami) w struct msghdr. Struktura nie ma domyślnego konstruktora, ponieważ jest to struktura C. Miałem wrażenie, że formularz = {0} doprowadził do zerowej inicjalizacji wszystkich pól (co byłoby dla mnie w porządku), ale komunikat o błędzie g++ sugeruje, że nie.

Jakie są moje opcje?

+0

możliwy duplikat [Dlaczego kompilator rzuca to ostrzeżenie: "brak inicjatora"? Czy struktura nie została zainicjowana?] (Http://stackoverflow.com/questions/1538943/why-is-tiler-throwing-this-warning-missing-initializer-isnt-the-stru) – ergosys

Odpowiedz

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

The g ++ -Wextra poziom ostrzegawczy jest IMHO nie bardzo przydatne.

Kod, który posiadasz, jest również formalnie OK dla "C struct", w standardzie znanym jako POD (Plain Old Data). Ale twój kod jawnie inicjuje pierwszy element z wartością 0. To niekoniecznie działa dla agregatu, który nie jest POD, np. z std::string jako pierwszym elementem, podczas gdy czysty {} będzie działał także dla tego.

Podsumowując, często POD, taki jak ten, z którym masz do czynienia, ma licznik bajtów jako pierwszy element, a następnie możesz wykonać polecenie & hellip;

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

Może dodać STATIC_ASSERT że człon Liczba bajtów jest pierwszy (przy przesunięciu 0).

Cheers & HTH,

+1

Nie zgadzam się ze zdaniem _ Poziom ostrzeżenia g ++ -Wextra nie jest zbyt użyteczny. – peoro

+1

@peoro: OK. Dodałem "IMHO".:-) –

+0

Dzięki za wiadomość Alf, dobrze jest wiedzieć, że to '-Wextra', która jest zepsuta i nie rozumiem C++ :-) –

4

To powinno działać:

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

popraw literówkę i Usuwam odpowiedź, pokonujesz mnie przez kilka sekund! :) – Nim

1

Jeśli nie można żyć z ostrzeżeniem i/lub nie chcą, aby wyłączyć ostrzeżenie, to myślę, że będzie ona musiała być jawne inicjalizacji poprzez np memset:

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

może, jeśli nie chcesz używać domyślnego konstruktora można po prostu użyć funkcji preprocesora jak:.

#ifdef LINUX 
//init for linux 
#endif 

#ifdef WINDOWS 
//init for windows 
#endif 

i tak dalej

+0

Przykro mi, nie rozumiem, jak to zainicjuje strukturę. Definicja struktury jest poza moją kontrolą (będąc w 'socket.h'). Czy możesz podać przykład tego, jak powinna wyglądać inicjalizacja struktury w twoim proponowanym rozwiązaniu? –

+0

Chciałem ci powiedzieć, jak wygląda struktura dla każdej platformy. Możesz go zainicjować dla każdej platformy, ponieważ znasz wszystkie pola. Jeśli więc gdzieś w aplikacji napiszesz na przykład #define LINUX, część #ifdef LINUX zostanie dodana przez preprocesor do kodu i wykonana. W takim przypadku funkcja będzie inna dla różnych platform. http://stackoverflow.com/questions/2989810/which-cross-platform-preprocessor-defines-win32-or-win32-or-win32 - może być przydatne – Andrew

+0

OK, to ma sens, dzięki za wyjaśnienie. –

2

Specyficzny flag ostrzeżenie co powoduje, że jest to -Wmissing-field-initializers, który jest włączony jako część -Wextra. Najprostszym sposobem uniknięcia tego (fałszywego) ostrzeżenia jest zatem użycie -Wno-missing-field-initializers.