estructuras - ¿Cuál es la forma correcta de inicializar una estructura muy grande?
estructuras en c++ pdf (5)
Como han dicho otros, memset es el camino a seguir. Sin embargo, no use memset en objetos C ++, particularmente aquellos con métodos virtuales. El sizeof( foo )
incluirá la tabla de punteros de funciones virtuales, y hacer un memset sobre eso causará una gran aflicción.
Si memset no resuelve el problema por sí mismo, simplemente haga un memset y luego inicialice cualquier miembro que no sea cero (es decir, los valores de coma flotante no IEEE).
En nuestro código solíamos tener algo como esto:
*(controller->bigstruct) = ( struct bigstruct ){ 0 };
Esto solía funcionar muy bien, y luego actualizamos versiones de GCC y de repente comenzamos a ver desbordamientos de pila. Al observar el ensamblaje, el antiguo código GCC (2.x) básicamente hacía esto:
memset(controller->bigstruct, 0, sizeof(struct bigstruct));
El nuevo GCC (3.4.x) estaba haciendo esto
struct bigstruct temp = { 0 };
controller->bigstruct = temp;
Después de revisar las especificaciones C99, pude ver por qué; C99 básicamente requiere que existan estructuras anónimas en la pila. Es un buen concepto, pero esta estructura tenía 4 megabytes de tamaño, ¡y solo tenía la intención de existir en montón!
Hemos recurrido a crear nuestra propia función de "inicialización" que establece explícitamente a los miembros, pero eso es feo y un dolor de cabeza de mantenimiento. No considero que memset sea una solución adecuada, porque no puedo saber que un valor de bit de 0 es un valor de cero apropiado para el tipo (Nit-Picking, lo sé, pero ahí está, no me importa eso). el compilador lo hace, porque puede saber)
¿Cuál es la forma "correcta", o al menos la mejor, para inicializar una estructura grande como esta?
Para aclarar mejor por qué creo que memset no es una solución: las reglas de inicialización de miembros no inicializados explícitamente son las mismas que la inicialización estática, y son las siguientes: - Si tiene tipo de puntero, se inicializa a un puntero nulo; - Si tiene tipo aritmético, se inicializa a cero (positivo o sin signo); ...
''memset'' configurará la memoria en el patrón de bits cero, que no es necesariamente lo mismo. Imagine un sistema que no usa números de punto flotante IEEE. Inusual, pero compatible con C. La representación de 0.0 no tiene por qué significar "todos los bits cero", podría ser algo conveniente para el procesador.
La función de inicialización privada no es fea, sino más bien una buena forma de OO para inicializar objetos (estructuras). Supongo que su estructura no es de 4MB de punteros, así que supongo que la solución debería ser así:
void init_big_struct(struct bigstruct *s)
{
memset(s, 0, sizeof(struct bigstruct));
s->some_pointer = NULL; // Multiply this as needed
}
Por otra parte, nuestro código se ejecuta en más de 20 sistemas operativos integrados y una gran cantidad de hardwares diferentes, nunca se encuentra ningún problema con solo memset de la estructura.
Si no quiere usar memset, siempre puede declarar una copia estática de su estructura y usar memcpy, que le dará un rendimiento similar. Esto agregará 4 megas a su programa, pero probablemente sea mejor que configurar elementos individuales.
Dicho esto, si GCC estaba usando memset, y ya era lo suficientemente bueno, sugeriría que ahora es lo suficientemente bueno.
hmm - antes que nada hacer una función init y configurar cada miembro explícitamente ES LO CORRECTO - es la manera en que trabajan los constructores en los lenguajes OO.
y segundo: ¿alguien sabe un hardware que implementa números de punto flotante no IEEE? - tal vez Commodore 64 o algo así ;-)
memset es el camino a seguir. No tienes muchas alternativas.
Haz algo como:
#define InitStruct(var, type) type var; memset(&var, 0, sizeof(type))
Para que solo tengas que:
InitStruct(st, BigStruct);
Y luego usa st como de costumbre ...
No entiendo cómo "0" no es un tipo "0" válido para una estructura. La única forma de "inicializar en masa" una estructura es establecer toda su memoria en un valor; de lo contrario, tendrías que hacer una lógica extra para decirle que use un patrón de bits específico por miembro. El mejor patrón de bits "genérico" para usar es 0.
Además, esta es la misma lógica que usaste al hacer
*(controller->bigstruct) = *( struct bigstruct ){ 0 };
Por lo tanto, no me da renuencia a usarlo :)
El primer comentario a esta publicación me hizo investigar un poco antes de llamarlo idiota y encontré esto:
http://www.lysator.liu.se/c/c-faq/c-1.html
Muy interesante; si pudiera votar un comentario, lo haría :)
Dicho esto, su única opción si desea apuntar a arquitecturas arcaicas con valores nulos nulos es seguir haciendo la inicialización manual a ciertos miembros.
Gracias Thomas Padron-McCarthy! Aprendí algo nuevo hoy :)