Как я должен правильно инициализировать структуру C из C ++? - PullRequest
7 голосов
/ 24 января 2011

У меня есть следующий код в файле 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++ подсказывает, что нет.

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

Ответы [ 5 ]

8 голосов
/ 24 января 2011
void someFunc()
{
    msghdr msg = {};  // <<< All members zero-initialized
}

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

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

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

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

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

Приветствия и hth.,

4 голосов
/ 24 января 2011

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

memset(&msg, 0, sizeof(msg));
2 голосов
/ 26 января 2011

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

1 голос
/ 24 января 2011

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

memset(&msg, 0, sizeof(msg));
0 голосов
/ 24 января 2011

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

#ifdef LINUX
//init for linux
#endif

#ifdef WINDOWS
//init for windows
#endif

и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...