2009-10-08 15 views
58

Estoy creando algún tipo de frontend para un programa. Para iniciar el programa, estoy usando la llamada CreateProcess(), que entre otras cosas recibe un puntero a una estructura STARTUPINFO. Para inicializar la estructura que solía hacer:¿Por qué el compilador lanza esta advertencia: "falta el inicializador"? ¿No se inicializó la estructura?

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

Al compilar el programa con GCC permite a estos conjuntos de advertencias -Wall -Wextra me da una advertencia que indica que hay una falta de inicialización que apunta a la primera línea.

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

así que terminé haciendo:

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

Y de esta manera 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 inicializó la estructura? ¿Cuál recomendaría usted?

+0

No me da ninguna advertencia usando VC2008/W4 – AraK

+0

Sí, gracias, también en este caso. Al menos GCC 4.4.1 y 4.5.0 dan esa advertencia, puede deberse al relleno que mencionas. – Shantia

+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 los 4 miembros. – pmg

Respuesta

72

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

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

En pocas palabras, aunque - inicialización de la estructura con sólo {0} de hecho, cero inicializar todo el asunto.

El estándar C99 dice lo siguiente en 6.7.8/21 "inicialización" - Sematics:

Si hay menos inicializadores en una lista corsé-cerrado que elementos o miembros de un agregado, o menos caracteres en un literal de cadena usado para inicializar una matriz de tamaño conocido que no hay elementos en la matriz, el resto del agregado se inicializará implícitamente de la misma manera que los objetos que tienen una duración de almacenamiento estática.

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

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

+0

GCC también acepta las llaves vacías ('{}') como una extensión del lenguaje C. –

+2

Ver también: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750 – pixelbeat

+16

Tuve que agregar '-Wno-missing-field-initializers' y ' -Wno-missing-braces' por lo que GGC dejó de gemir sobre mí poniendo '= {0};' para mis estructuras. ¿Alguien sabe si deshabilitar estas advertencias perderá advertencias por otras cosas que no sean '= {0};' para las estructuras? –

13

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

STARTUPINFO startupInfo = STARTUPINFO(); 
  • acaba de hacer exactamente hace esto un par de días
+0

Un posible escollo con esta respuesta es que en C++ 98 esto no fue cero. Inicializa los campos. El comportamiento de inicialización cero se agregó en C++ 03. –

10

Usted pidió tantas advertencias como sea posible utilizando -Wall -Wextra.

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

puede suprimir esta advertencia mediante la adición de -Wno-desaparecidos-campo-inicializadores

7

Esta página Web se analiza la cuestión de fondo con gran detalle: http://ex-parrot.com/~chris/random/initialise.html

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

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

Lamentablemente, esto sólo funciona en sonido metálico y no parece trabajar en GCC.

+2

Puedo confirmar: '#pragma Diagnóstico de GCC ignorado" -Wmissing-field-initializers "' aceptado por el compilador GCC 4.2.1 pero no hacer nada. No estoy seguro sobre las nuevas versiones de gcc – Speakus

+0

@speakus, puedo confirmar que está trabajando con la última versión (al momento de escribir) gcc (7.3.0). – cydef

1

En C++ puede usar boost::initialized_value para deshacerse de esta advertencia. Tengo advertencias desactivadas para boost; así que no sé si esto causaría otras advertencias en su caso. De esta manera, no tiene que deshabilitar la advertencia.

Ejemplo:

T bla = boost::initialized_value; 
Cuestiones relacionadas