web-dev-qa-db-fra.com

Pourquoi le compilateur lance-t-il cet avertissement: "initialiseur manquant"? La structure n'est-elle pas initialisée?

Je crée une sorte de frontend pour un programme. Pour lancer le programme, j'utilise l'appel CreateProcess(), qui reçoit entre autres un pointeur vers une structure STARTUPINFO. Pour initialiser la structure que j'avais l'habitude de faire:

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

Lors de la compilation du programme avec GCC, l'activation de ces ensembles d'avertissements -Wall -Wextra cela me donne un avertissement disant qu'il y a un initialiseur manquant pointant vers la première ligne.

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

J'ai donc fini par faire:

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

Et de cette façon, le compilateur ne donne aucun avertissement. La question est, quelle est la différence entre ces façons d'initialiser une structure? En utilisant la première méthode, la structure n'est-elle pas initialisée? Lequel recommanderiez-vous?

68
Shantia

GCC est juste trop paranoïaque - sans raison valable à mon avis, mais il est certainement vrai que les responsables de GCC en savent beaucoup plus sur les nuances de C que je fais.

Voir ce petit fil de discussion sur le problème sur la liste de diffusion GCC:

En bout de ligne - initialiser la structure avec juste {0} en fait zéro initialisera le tout.

La norme C99 dit ce qui suit dans 6.7.8/21 "Initialisation - Sématique":

S'il y a moins d'initialiseurs dans une liste entre accolades qu'il n'y a d'éléments ou de membres d'un agrégat, ou moins de caractères dans un littéral de chaîne utilisé pour initialiser un tableau de taille connue qu'il n'y a d'éléments dans le tableau, le reste de l'agrégat doit être initialisé implicitement comme les objets qui ont une durée de stockage statique.

C90 dit essentiellement la même chose en 6.5.7 avec une formulation un peu différente (en d'autres termes, C99 n'a pas ajouté quelque chose de nouveau ici).

Notez également qu'en C++, cela a été étendu afin qu'un ensemble d'accolades vide, "{} ", effectuerait l'initialisation de la valeur sur un objet car il y avait des situations (comme des modèles) où vous ne saviez même pas quels membres ou combien de membres un type pouvait avoir. Donc, non seulement c'est une bonne pratique, mais parfois nécessaire pour avoir une liste d'initialisation plus courte que le nombre de membres qu'un objet peut avoir.

82
Michael Burr

Cela peut être facilement corrigé pour GCC dans les programmes C++ en initialisant la structure comme

STARTUPINFO startupInfo = STARTUPINFO();
  • vient de faire exactement cela il y a quelques jours
17
dmityugov

Vous avez demandé autant d'avertissements que possible en utilisant -Wall -Wextra.

Dans ce cas, vous obtenez un avertissement qui vous indique que vous n'avez pas spécifié tous les champs, ce qui est parfaitement valide, mais aurait pu être involontaire.

Vous pouvez supprimer cet avertissement en ajoutant -Wno-missing-field-initializers

13
ecotax

Cette page Web aborde le problème sous-jacent de manière très détaillée: http://ex-parrot.com/~chris/random/initialise.html

Pour contourner le problème, ma solution actuelle consiste à supprimer sélectivement cet avertissement:

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

Malheureusement, cela ne fonctionne qu'en clang et ne semble pas fonctionner dans GCC.

9
JanX2

En C++, vous pouvez utiliser boost::initialized_value pour supprimer cet avertissement. J'ai des avertissements désactivés pour boost; donc je ne sais pas si cela entraînerait d'autres avertissements dans votre cas. De cette façon, vous n'avez pas à désactiver l'avertissement.

Exemple:

T bla = boost::initialized_value;
1
Michael F Hancock