Подтвердить что ты не робот

Почему компилятор бросает это предупреждение: "Отсутствует инициализатор"? Не инициализирована ли структура?

Я создаю какой-то интерфейс для программы. Для запуска программы я использую вызов CreateProcess(), который, среди прочего, получает указатель на структуру STARTUPINFO. Для инициализации структуры, которую я использовал:

STARTUPINFO startupInfo = {0}; // Or even '\0'.
startupInfo.cb = sizeof(startupInfo);

При компиляции программы с включенным GCC этими наборами предупреждений -Wall -Wextra это дает мне предупреждение о том, что отсутствует инициализатор, указывающий на первую строку.

warning: missing initializer
warning: (near initialization for 'startupInfo.lpReserved')

Итак, я закончил:

STARTUPINFO startupInfo;
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);

И таким образом компилятор не дает никаких предупреждений. Вопрос в том, в чем разница между этими способами инициализации структуры? Используя первый метод, не инициализируется ли структура? Какой из них вы бы порекомендовали?

4b9b3361

Ответ 1

GCC просто чересчур параноик - по какой-то веской причине, на мой взгляд, но тогда, безусловно, верно, что поддерживающие GCC знают намного больше о нюансах C, которые я делаю.

См. эту небольшую дискуссию о проблеме в списке рассылки GCC:

Нижняя строка, хотя - инициализация структуры только с помощью {0} будет фактически нулевой инициализировать все это.

В стандарте C99 говорится следующее в 6.7.8/21 "Инициализация - семантика":

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

C90 говорит, что в 6,5.7 в той же форме немного отличается (другими словами, C99 не добавил здесь ничего нового).

Также обратите внимание, что в С++ это было расширено, так что пустой набор фигурных скобок "{}" выполнил бы инициализацию значения для объекта, потому что были ситуации (например, шаблоны), когда вы даже не знали, что члены или количество членов, которое может иметь тип. Таким образом, это не только хорошая практика, но и необходимость иногда иметь список инициализаторов, который меньше, чем количество членов, которые могут иметь объекты.

Ответ 2

Это может быть легко исправлено для GCC в программах на С++, инициализируя структуру как

STARTUPINFO startupInfo = STARTUPINFO();
  • просто сделал это несколько дней назад

Ответ 3

Вы запросили как можно больше предупреждений, используя -Wall -Wextra.

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

Вы можете подавить это предупреждение, добавив -Wno пропущенного-полевые инициализаторы

Ответ 4

На этой веб-странице подробно рассматриваются основные проблемы: http://ex-parrot.com/~chris/random/initialise.html

В качестве рабочего решения мое текущее решение заключается в выборочном пресечении этого предупреждения:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
STARTUPINFO startupInfo = {0};
#pragma clang diagnostic pop

К сожалению, это работает только в clang и, похоже, не работает в GCC.

Ответ 5

В С++ вы можете использовать boost::initialized_value, чтобы избавиться от этого предупреждения. У меня есть предупреждения для boost; поэтому я не знаю, приведет ли это к другим предупреждениям в вашем случае. Таким образом, вам не нужно отключать предупреждение.

Пример:

T bla = boost::initialized_value;