Почему компилятор выдает это предупреждение: «отсутствует инициализатор»? Разве структура не инициализирована? - PullRequest
67 голосов
/ 08 октября 2009

Я создаю какой-то интерфейс для программы. Для запуска программы я использую вызов 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);

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

Ответы [ 5 ]

80 голосов
/ 08 октября 2009

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

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

Суть в том, что инициализация структуры с помощью {0} фактически приведет к нулю инициализации всего объекта.

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

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

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

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

17 голосов
/ 09 октября 2009

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

STARTUPINFO startupInfo = STARTUPINFO();
  • только что сделал это несколько дней назад
12 голосов
/ 22 марта 2011

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

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

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

8 голосов
/ 15 февраля 2012

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

В качестве обходного пути мое текущее решение состоит в том, чтобы выборочно подавить это предупреждение:

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

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

1 голос
/ 09 сентября 2013

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

Пример:

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