¿Por qué el compilador lanza esta advertencia: "falta el inicializador"? ¿No está inicializada la estructura?

79

Estoy creando una especie de interfaz para un programa. Para lanzar el programa estoy usando la llamada CreateProcess(), que entre otras cosas recibe un puntero a una STARTUPINFOestructura. Para inicializar la estructura que solía hacer:

Al compilar el programa con GCC que habilita estos conjuntos de advertencias -Wall -Wextra, me da una advertencia que dice que falta un inicializador que apunta a la primera línea.

Así que terminé haciendo:

Y de esta forma el compilador no da ninguna advertencia. La pregunta es, ¿cuál es la diferencia entre estas formas de inicializar una estructura? Usando el primer método, ¿no se inicializa la estructura? ¿Cuál recomendarías?

Shantia
fuente
1
La advertencia es solo eso: una advertencia. Está bien ignorar esta advertencia específica en esta ocasión específica. El compilador emite la advertencia para ayudarlo en casos como: struct struct_with_four_fields x = {1, 2, 3};donde solo se inicializan 3 de 4 miembros.
pmg
En mi comentario anterior, el cuarto miembro se inicializa a 0.
pmg
5
La advertencia sobre la falta de inicializadores no es descabellada en general; si tiene una estructura con 4 miembros y proporciona inicializadores para solo 3 de ellos, es probable que sea un error. Pero { 0 }es un idioma común y bien definido para inicializar todos los miembros a cero (definido de forma recursiva para cada submiembro), por lo que las versiones posteriores de gcc se han modificado para no advertir sobre ese caso en particular.
Keith Thompson
@KeithThompson, ¿de qué estás hablando? Estoy usando gcc 4.8.2 , y desde la pregunta pasaron cinco años. PD: había un correo más, que quería vincular al final, pero para mi asombro falta. Probablemente el servidor de correo no guarde todos los mensajes, eso es triste, el correo sería útil para alguien que vuelva a encontrar el problema.
Hi-Angel
4
@ Hi-Angel: Cuando compilo un pequeño programa con gcc-4.8.1 en Solaris, aparece "advertencia: falta el inicializador". Cuando compilo el mismo programa con gcc-4.8.2 en Linux Mint, no recibo ninguna advertencia. Por cierto, la línea obj = {0};del mensaje al que se vinculó no es C válida y gcc 4.8.2 la rechaza como un error de sintaxis. Si está compilando como C ++, recuerde que es un lenguaje diferente y gcc usa una interfaz diferente; Las correcciones en el compilador C de gcc pueden aplicarse o no a g ++.
Keith Thompson

Respuestas:

87

GCC está siendo demasiado paranoico, sin una buena razón en mi opinión, pero es cierto que los mantenedores de GCC saben mucho más sobre los matices de C que yo.

Vea este pequeño hilo de discusión sobre el problema en la lista de correo de GCC:

Sin embargo, en pocas palabras: inicializar la estructura con solo {0}, de hecho, inicializará todo en cero.

El estándar C99 dice lo siguiente en 6.7.8 / 21 "Inicialización - Semántica":

Si hay menos inicializadores en una lista entre llaves que elementos o miembros de un agregado, o menos caracteres en un literal de cadena usado para inicializar un arreglo de tamaño conocido que elementos en el arreglo, el resto del agregado deberá inicializarse implícitamente de la misma manera que los objetos que tienen una duración de almacenamiento estático.

C90 dice esencialmente lo mismo en 6.5.7 con una redacción un poco diferente (en otras palabras, C99 no agregó nada nuevo aquí).

También tenga en cuenta que en C ++ esto se extendió para que un conjunto vacío de llaves, " {}", realizara la inicialización de valor en un objeto porque había situaciones (como plantillas) en las que ni siquiera sabría cuáles son los miembros o cuántos miembros de un tipo podría tener. Entonces, no solo es una buena práctica, sino que a veces es necesario tener una lista de inicializadores más corta que la cantidad de miembros que podría tener un objeto.

Michael Burr
fuente
19
Tuve que agregar -Wno-missing-field-initializersy -Wno-missing-bracespara que GGC dejara de quejarse de que yo ponía = {0};para mis estructuras. ¿Alguien sabe si al desactivar estas advertencias se perderán las advertencias para otras cosas que no sean = {0};estructuras?
Matt Clarkson
4
La corrección está presente en gcc 4.7.0 , pero no en gcc 4.6.3 .
empalmador
1
@splicer: ¿Cuál "la" solución? También estoy compilando mingw32-g++.exe (GCC) 4.7.2y obteniendo esta advertencia en el idioma anterior (incluso el caso exacto de STARTUPINFO).
Jan Hudec
2
@Jan Hudec: Revisión 172857 . Desafortunadamente, las URL de mis comentarios anteriores ya no funcionan. Aquí está el error asociado con la revisión: gcc.gnu.org/bugzilla/show_bug.cgi?id=36750
empalmador
9
Sigo recibiendo la advertencia incluso con gcc 4.9.3 cuando uso la llave vacía {}o los {0}inicializadores en mis clases de C ++: /
Kamil Kisiel
21

Esto se puede arreglar fácilmente para GCC en programas C ++ inicializando la estructura como

  • Hice exactamente esto hace unos días
dmityugov
fuente
1
Un posible error con esta respuesta es que en C ++ 98 esto no inicializó a cero los campos. El comportamiento de inicialización cero se agregó en C ++ 03.
MM
1
@MM Gracias por señalar el posible error, pero creo que en diciembre de 2018 esto ya no debería estar en el código como una situación peligrosa. Por cierto, ¡encuentro esta respuesta la mejor!
Peter VARGA
@AlBundy Desafortunadamente, todavía hay algunos compiladores que usan la inicialización de C ++ 98 (por ejemplo, el modo C ++ Builder XE5 de 32 bits que tengo abierto ahora mismo por coincidencia)
MM
Tuve que agregar más de 10 líneas de código a mi archivo debido a esto. Estoy realmente enojado Intenté pasar objetos anónimos en una llamada de función. Si utilicé {} o {0}, recibí esta advertencia (tratada como un error). Si usara () entonces gcc piensa que es una llamada a la función ...
bencemeszaros
15

Solicitó tantas advertencias como sea posible utilizando -Wall -Wextra.

En este caso, recibe una advertencia que le dice que no especificó todos los campos, lo cual es perfectamente válido, pero podría haber sido no intencional.

Puede suprimir esta advertencia agregando -Wno-missing-field-initializers

ecotasa
fuente
12

Esta página web analiza el problema subyacente con gran detalle: http://ex-parrot.com/~chris/random/initialise.html

Como solución temporal, mi solución actual es suprimir selectivamente esta advertencia:

Lamentablemente, esto solo funciona en clang y no parece funcionar en GCC.

JanX2
fuente
4
Puedo confirmar: #pragma GCC diagnostic ignored "-Wmissing-field-initializers"aceptado por el compilador GCC 4.2.1 pero no hago nada. no
estoy
1
@speakus, puedo confirmar que está funcionando con la última (en el momento de la escritura) gcc (7.3.0).
cydef
@cydef de acuerdo con otros comentarios y los informes de errores que he visto, GCC ya no advierte (a partir de GCC 5) sobre esto en absoluto, independientemente de #pragma clang diagnostic ignored "-Wmissing-field-initializers". Probablemente debería comprobar si este es el caso.
WD40
1

En C ++ puede utilizar boost::initialized_valuepara deshacerse de esta advertencia. Tengo las advertencias desactivadas para boost; así que no sé si esto causaría otras advertencias en su caso. De esta manera, no es necesario que desactive la advertencia.

Ejemplo:

Michael F Hancock
fuente