Inicializando una estructura a 0

116

Si tengo una estructura como esta:

typedef struct
{
    unsigned char c1;
    unsigned char c2;
} myStruct;

¿Cuál sería la forma más fácil de inicializar esta estructura a 0? ¿Sería suficiente lo siguiente?

myStruct _m1 = {0};

o ¿tendría que iniciar explícitamente cada miembro en 0?

myStruct _m2 = {0,0};
Daan Timmer
fuente

Respuestas:

142

El primero es más fácil ( implica menos escritura ) y está garantizado que funciona, todos los miembros se establecerán en 0[Ref 1] .
El segundo es más legible.

La elección depende de la preferencia del usuario o de la que exige su estándar de codificación.

[Ref 1] Referencia C99 Standard 6.7.8.21:

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 forma que los objetos que tienen una duración de almacenamiento estático.

Buena lectura:
C y C ++: inicialización parcial de la estructura automática

Alok Save
fuente
9
Además, estoy usando = {};Sin embargo, no estoy seguro de si esto es válido.
William Entriken
15
@FullDecent llaves vacías para inicialización es una extensión GNU.
a3f
2
@ alias65536 La pregunta tiene la etiqueta C, no C ++.
a3f
3
Recibí un error: "faltan llaves alrededor del inicializador [-Werror = missing-braces]" probablemente debido a una matriz de miembros: /
DrumM
3
@Edenia. Estoy en desacuerdo. Ya sé lo que foo = {0}significa. Si lo viera foo = ZERO_FULL, tendría que grep para la definición de ZERO_FULL.
Andrew Bainbridge
32

Si los datos son una variable estática o global, se rellenan con ceros de forma predeterminada, así que simplemente declare myStruct _m;

Si los datos son una variable local o una zona asignada al montón, bórrelos con algo memsetasí:

memset(&m, 0, sizeof(myStruct));

Los compiladores actuales (por ejemplo, versiones recientes de gcc) optimizan eso bastante bien en la práctica. Esto funciona solo si todos los valores cero (incluidos los punteros nulos y el punto flotante cero) se representan como todos los bits cero, lo cual es cierto en todas las plataformas que conozco (pero el estándar C permite implementaciones donde esto es falso; no conozco tal implementación) .

Quizás podría codificar myStruct m = {};o myStruct m = {0};(incluso si el primer miembro de myStructno es un escalar).

Mi sensación es que usar memsetpara estructuras locales es lo mejor, y transmite mejor el hecho de que en tiempo de ejecución, algo debe hacerse (mientras que, por lo general, los datos globales y estáticos pueden entenderse como inicializados en tiempo de compilación, sin ningún costo en tiempo de ejecución) .

Basile Starynkevitch
fuente
7
No hay garantía de que establecer todos los bytes de la estructura en 0sea ​​equivalente a inicializar todos los miembros de la estructura con 0aunque. En muchas plataformas esto será cierto, pero no universalmente.
Sander De Dycker
1
¿Puedes compartir un ejemplo, Sander? Genuina curiosidad. (Obviamente, no universalmente cierto no significa necesariamente que haya una excepción fácil de explicar, pero si la hay ...)
Steven Fisher
2
El estándar C permite que el puntero nulo (o un número de coma flotante cero) sea representado en la memoria por algo más que todos los bits cero. Muy pocas y extrañas implementaciones están haciendo eso (no puedo nombrar ninguna).
Basile Starynkevitch
-1, puede encontrar fea la inicialización que el OP pregunta sobre, pero es exactamente lo que prevé el estándar y que todos los compiladores pueden optimizar fácilmente. Entonces, el formulario {}no es válido en C, solo está disponible en C ++.
Jens Gustedt
7
@Steven: Solo puedo pensar en plataformas oscuras y / o antiguas. Las preguntas frecuentes de C tienen una lista de plataformas que tenían un NULLpuntero que no era todo 0bits: c-faq.com/null/machexamp.html . Y luego existe la posibilidad de que la plataforma no esté usando IEEE 754 para representar valores de punto flotante, sino que use alguna otra representación que no tenga un valor total de 0bits 0.0, pero es cierto que no conozco tal plataforma.
Sander De Dycker
19

Consulte §6.7.9 Inicialización:

21 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 se inicializarán implícitamente al igual que los objetos que tienen una duración de almacenamiento estático.

Entonces, sí, ambos funcionan. Tenga en cuenta que en C99 también se puede usar una nueva forma de inicialización, llamada inicialización designada:

myStruct _m1 = {.c2 = 0, .c1 = 1};
dirkgently
fuente
En particular, esto ya es C89: open-std.org/JTC1/SC22/WG14/www/docs/n1124.pdf#page=139 (Importante para objetivos de procesamiento de señales específicos)
Tobias