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, entre autres, reçoit un pointeur sur une structure STARTUPINFO . Pour initialiser la structure que je faisais auparavant:

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

Lors de la compilation du programme avec GCC permettant ces ensembles d’avertissements -Wall -Wextra il me donne un avertissement indiquant qu’il manque un initialiseur pointant vers la première ligne.

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

Donc j’ai 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 la suivante: quelle est la différence entre ces manières d’initialiser une structure? En utilisant la première méthode, la structure n’est-elle pas initialisée? Lequel recommanderiez-vous?

GCC est juste trop paranoïaque – sans raison pour moi, mais il est certainement vrai que les responsables du 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 de GCC:

En fin de compte, l’initialisation de la structure avec juste {0} ne va en fait pas initialiser le tout.

Le standard C99 indique ce qui suit dans 6.7.8 / 21 “Initialisation – Sémantique”:

S’il y a moins d’initialiseurs dans une liste entourée d’accolades qu’il 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 y a d’éléments dans le tableau, être initialisé implicitement de la même manière que les objects 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’ajoute rien de nouveau ici).

Notez également qu’en C ++, ceci a été étendu de sorte qu’un ensemble d’accolades vide, ” {} “, effectuerait l’initialisation de la valeur sur un object car il y avait des situations (comme des modèles) un type pourrait avoir. Donc, non seulement c’est une bonne pratique, mais il est parfois nécessaire d’avoir une liste d’initialisation plus courte que le nombre de membres qu’un object peut avoir.

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

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

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

Dans ce cas, vous recevez un avertissement vous indiquant 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-initializer

Cette page Web traite en détail du problème sous-jacent: http://ex-parrot.com/~chris/random/initialise.html

En guise de solution, 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 que dans le clang et ne semble pas fonctionner dans GCC.

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

Exemple:

 T bla = boost::initialized_value;