De este comentario en GCC error # 53119 :
En C,
{0}es el inicializador de cero universal equivalente al{}de C++ (este último no es válido en C). Es necesario utilizarlo siempre que se desee un objeto inicializado en cero de un tipo completo pero conceptualmente opaco o definido por la implementación. El ejemplo clásico en la biblioteca estándar de C esmbstate_t:mbstate_t state = { 0 }; /* correctly zero-initialized */versus el común pero no portátil:
mbstate_t state; memset(&state, 0, sizeof state);
Me parece extraño que la última versión no sea portátil (incluso para los tipos definidos por la implementación, el compilador tiene que saber el tamaño). ¿Cuál es el problema aquí y cuándo un memset(x, 0, sizeof x) no es portátil?
memset(p, 0, n) se establece en todos los bits-0.
Un inicializador de { 0 } establece el valor 0.
En casi cualquier máquina de la que haya oído hablar, los dos conceptos son equivalentes.
Sin embargo, ha habido máquinas en las que el valor de coma flotante 0.0 no estaba representado por un patrón de bits de todos los bits-0. Y ha habido máquinas en las que un puntero nulo tampoco estaba representado por un patrón de bits de todos los bits-0. En esas máquinas, un inicializador de { 0 } siempre le daría la inicialización cero que deseaba, mientras que memset podría no hacerlo.
Consulte también la pregunta 7.31 y la pregunta 5.17 en la lista de preguntas frecuentes de C.
Posdata: Sin embargo, no me queda claro por qué mbstate_t sería un "ejemplo clásico" de este problema.
PPS Otra diferencia, como lo señaló @ryker: memset establecerá cualquier "agujero" en una estructura rellenada en 0, mientras que establecer esa estructura en { 0 } podría no hacerlo.
La razón de esto tiene que ver con cómo se representan los tipos.
La sección 6.7.9p10 del estándar C describe cómo se inicializan los campos de la siguiente manera:
Si un objeto que tiene duración de almacenamiento automático no se inicializa explícitamente, su valor es indeterminado. Si un objeto que tiene una duración de almacenamiento estático o de subprocesos no se inicializa
explícitamente, entonces:
si tiene un tipo de puntero, se inicializa a un puntero nulo;
si es de tipo aritmético, se inicializa a cero (positivo o sin signo);
si es un agregado, cada miembro se inicializa (recursivamente) de acuerdo con estas reglas, y cualquier relleno se inicializa a cero bits;
si es una unión, el primer miembro nombrado se inicializa (recursivamente) de acuerdo con estas reglas, y cualquier relleno se inicializa a cero bits
Y p21 también dice:
Si hay menos inicializadores en una lista entre llaves que elementos o miembros de un agregado, o menos caracteres en una cadena literal utilizada para inicializar una matriz de tamaño conocido que elementos en la matriz, el resto del agregado debe inicializarse implícitamente igual que los objetos que tienen una duración de almacenamiento estática
La diferencia entre esto y establecer todos los bytes en cero es que algunos de los valores anteriores pueden no estar necesariamente representados por todos los bits en cero.
Por ejemplo, existen algunas arquitecturas donde la dirección 0 es una dirección válida. Esto significa que un puntero nulo no se representa como todos los bits cero. (Nota: (void *)0 se especifica como una constante de puntero nulo por el estándar, sin embargo, la implementación tratará esto como la representación de un puntero nulo)
El estándar tampoco exige una representación particular para los tipos de punto flotante. Si bien la representación más común, IEEE754, usa todos los bits 0 para representar el valor +0, esto no es necesariamente cierto para otras representaciones.
Notando una diferencia en el comportamiento entre los dos métodos...
En ...= {0}; si existen bytes de relleno, no se borrarán.
Pero una llamada a memset() borrará el relleno.
desde aquí
"La posible implementación de mbstate_t es un tipo de estructura que contiene una matriz que representa el carácter multibyte incompleto, un contador de enteros que indica la cantidad de bytes en la matriz que se han procesado y una representación del estado de cambio actual".
En el caso de que mbstate_t se implemente como una struct , es notable que {0} no establecerá los bytes de relleno que puedan existir en zero , lo que hace discutible la siguiente suposición:
mbstate_t state = { 0 }; /* correctly zero-initialized */ memset() sin embargo incluye bytes de relleno.
memset(state , 0, sizeof state);//all bytes in memory region of test will be cleared