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


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

STARTUPINFO startupInfo = {0}; // Or even ''.
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);

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

5 63

5 ответов:

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

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

итог хотя-инициализация структуры только с {0} фактически ноль инициализирует все это.

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

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

C90 говорит по существу то же самое в 6.5.7 с немного другой формулировкой (другими словами, C99 не добавил Здесь ничего нового).

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

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

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

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

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

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

на этой веб-странице подробно обсуждается основная проблема: 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.

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

пример:

T bla = boost::initialized_value;