Tengo una gran matriz en C (no C ++ si eso hace la diferencia). Quiero inicializar a todos los miembros del mismo valor.
Podría jurar que una vez conocí una manera simple de hacer esto. Podría usar memset()
en mi caso, pero ¿no hay una manera de hacer esto que esté integrada en la sintaxis de C?
enum { HYDROGEN = 1, HELIUM = 2, CARBON = 6, NEON = 10, … };
ystruct element { char name[15]; char symbol[3]; } elements[] = { [NEON] = { "Neon", "Ne" }, [HELIUM] = { "Helium", "He" }, [HYDROGEN] = { "Hydrogen", "H" }, [CARBON] = { "Carbon", "C" }, … };
. Si elimina los puntos suspensivos…
, esos fragmentos se compilan bajo C99 o C11.memset()
discusión específica: stackoverflow.com/questions/7202411/… Creo que solo funciona para 0.Respuestas:
A menos que ese valor sea 0 (en cuyo caso puede omitir alguna parte del inicializador y los elementos correspondientes se inicializarán a 0), no hay una manera fácil.
Sin embargo, no pase por alto la solución obvia:
Los elementos con valores faltantes se inicializarán a 0:
Entonces esto inicializará todos los elementos a 0:
En C ++, una lista de inicialización vacía también inicializará cada elemento a 0. Esto no está permitido con C:
Recuerde que los objetos con una duración de almacenamiento estático se inicializarán a 0 si no se especifica ningún inicializador:
Y ese "0" no necesariamente significa "todos los bits cero", por lo que usar lo anterior es mejor y más portátil que memset (). (Los valores de coma flotante se inicializarán a +0, los punteros a valor nulo, etc.)
fuente
Si su compilador es GCC, puede usar la siguiente sintaxis:
Consulte la descripción detallada: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html
fuente
int
s en datos estáticos, que es 256 K, exactamente el aumento de tamaño que ha observado.int
s,int foo1 = 1, foo2 = 1, ..., foo65536 =1;
obtendrá el mismo aumento de tamaño.bool array[][COLS] = { [0...ROWS-1][0...COLS-1] = true}
, aunque no estoy seguro de que sea más legible que el formulario completo.Para inicializar estáticamente una matriz grande con el mismo valor, sin copiar y pegar múltiples, puede usar macros:
Si necesita cambiar el valor, debe hacer el reemplazo en un solo lugar.
Editar: posibles extensiones útiles
(cortesía de Jonathan Leffler )
Puede generalizar esto fácilmente con:
Se puede crear una variante usando:
que funciona con estructuras o matrices compuestas.
Los nombres de las macros son negociables.
fuente
VAL_1X
no es un número entero sino una lista. Al igual que los estados Amigable, este también es el camino a seguir para los sistemas embebidos en los que desea definir los valores de inicio de una memoria EEPROM o Flash. En ambos casos no puedes usarmemset()
.Si desea asegurarse de que cada miembro de la matriz se inicialice explícitamente, simplemente omita la dimensión de la declaración:
El compilador deducirá la dimensión de la lista de inicializadores. Desafortunadamente, para las matrices multidimensionales solo se puede omitir la dimensión más externa:
está bien, pero
no es.
fuente
int myPoints[10][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
Vi un código que usaba esta sintaxis:
Donde se vuelve particularmente útil es si está haciendo una matriz que utiliza enumeraciones como índice:
Esto mantiene las cosas en orden, incluso si usted escribe algunos de los valores de enumeración fuera de orden.
Puede encontrar más información sobre esta técnica aquí y aquí .
fuente
char const *array[] = { ... };
o inclusochar const * const array[] = { ... };
, ¿no?Creo que esto es mejor que
en caso de que cambie el tamaño de la matriz.
fuente
memset(myArray, VALUE, ARRAY_SIZE);
Puede hacer todo lo relacionado con el inicializador estático como se detalla anteriormente, pero puede ser un verdadero fastidio cuando cambia el tamaño de su matriz (cuando su matriz se embebe, si no agrega los inicializadores adicionales apropiados, obtiene basura).
memset le proporciona un tiempo de ejecución correcto para hacer el trabajo, pero ningún resultado de tamaño de código realizado correctamente es inmune a los cambios de tamaño de la matriz. Usaría esta solución en casi todos los casos cuando la matriz fuera más grande que, digamos, unas pocas docenas de elementos.
Si fuera realmente importante que la matriz se declarara estáticamente, escribiría un programa para escribir el programa por mí y hacerlo parte del proceso de compilación.
fuente
memset
para inicializar la matriz?Aquí hay otra forma:
Ver:
Extensiones C
Inits designados
Luego haga la pregunta: ¿Cuándo se pueden usar extensiones C?
El ejemplo de código anterior está en un sistema integrado y nunca verá la luz de otro compilador.
fuente
Para inicializar los tipos de datos 'normales' (como las matrices int), puede usar la notación de paréntesis, pero pondrá a cero los valores después de la última si todavía hay espacio en la matriz:
fuente
Si la matriz resulta ser int o algo con el tamaño de int o el tamaño de su patrón de memoria se ajusta a tiempos exactos en un int (es decir, todos los ceros o 0xA5A5A5A5), la mejor manera es usar memset () .
De lo contrario, llame a memcpy () en un bucle que mueve el índice.
fuente
Una respuesta ligeramente irónica; escribe la declaración
en su lenguaje favorito con capacidad de matriz (el mío es Fortran, pero hay muchos otros), y vincúlelo a su código C. Probablemente quieras envolverlo para que sea una función externa.
fuente
Hay una forma rápida de inicializar una matriz de cualquier tipo con un valor dado. Funciona muy bien con matrices grandes. El algoritmo es el siguiente:
Para la matriz de
1 000 000
elementosint
, es 4 veces más rápido que la inicialización de bucle normal (i5, 2 núcleos, 2.3 GHz, memoria 4GiB, 64 bits):loop runtime 0.004248 [seconds]
memfill() runtime 0.001085 [seconds]
fuente
memfill()
código toma alrededor de 1200 µs. Sin embargo, en las iteraciones posteriores, el ciclo toma alrededor de 900-1000 µs mientras que elmemfill()
código toma 1000-1300 µs. La primera iteración probablemente se ve afectada por el tiempo para llenar el caché. Invierte las pruebas ymemfill()
es lento la primera vez.Nadie ha mencionado el orden del índice para acceder a los elementos de la matriz inicializada. Mi código de ejemplo le dará un ejemplo ilustrativo.
El resultado es:
fuente
<iostream>
No es válidoC
comostd::cout
,std::cin
, etc. forma parte de lastd::namespace
yC
no soportanamespaces
. Intenta usar<stdio.h>
for en suprintf(...)
lugar.Cortando toda la charla, la respuesta corta es que si activa la optimización en tiempo de compilación, no lo hará mejor que esto:
Bonificación adicional: el código es realmente legible :)
fuente
ejemplo: int array [10]; memset (matriz, -1, 10 * sizeof (int));
fuente
Dará la o / p 5 5 5 5 5 5 ...... hasta el tamaño de toda la matriz
fuente
Sé que el usuario
Tarski
respondió a esta pregunta de manera similar, pero agregué algunos detalles más. Perdona parte de mi C porque estoy un poco oxidado porque estoy más inclinado a querer usar C ++, pero aquí está.Si conoce el tamaño de la matriz con anticipación ...
Hay algunas advertencias arriba; uno es que
UINT myArray[size];
no se inicializa directamente después de la declaración, sin embargo, el siguiente bloque de código o llamada de función inicializa cada elemento de la matriz al mismo valor que desea. La otra advertencia es que tendrías que escribir unainitializing function
para cada una de lastype
que admitirás y también deberías modificar laprintArray()
función para admitir esos tipos.Puede probar este código con un compilador en línea que se encuentra aquí .
fuente
Para la inicialización retrasada (es decir, inicialización del constructor de miembros de clase) considere:
fuente
Sé que la pregunta original menciona explícitamente C y no C ++, pero si usted (como yo) vino aquí buscando una solución para las matrices de C ++, aquí hay un buen truco:
Si su compilador admite expresiones de plegado , puede usar la plantilla de magia y
std::index_sequence
generar una lista de inicializador con el valor que desee. Y puedes igualarloconstexpr
y sentirte como un jefe:Puedes echar un vistazo al código en el trabajo (en Wandbox)
fuente
No veo requisitos en la pregunta, por lo que la solución debe ser genérica: inicialización de una matriz posiblemente multidimensional no especificada construida a partir de elementos de estructura posiblemente no especificados con un valor de miembro inicial:
Resultado:
EDITAR:
start+element_size
cambiado a(char*)start+element_size
fuente
sizeof(void)
es válido.memcpy()
superponen con el espacio de destino. Con una implementación ingenua dememcpy()
, puede funcionar, pero no es necesario que el sistema lo haga funcionar.En el pasado (y no digo que sea una buena idea), configuraríamos el primer elemento y luego:
memcpy (&element [1], &element [0], sizeof (element)-sizeof (element [0]);
Ni siquiera estoy seguro de que funcionaría más (eso dependería de la implementación de memcpy) pero funciona copiando repetidamente el elemento inicial al siguiente, incluso funciona para matrices de estructuras.
fuente
memcpy
pero especificadas en orden de copia de arriba a abajo en caso de superposición, pero no lo hace.memmove()
no lo hace funcionar.Si quiere decir en paralelo, creo que el operador de coma cuando se usa junto con una expresión puede hacer eso:
o si te refieres a una sola construcción, puedes hacerlo en un ciclo for:
// Tenga en cuenta que el operador de coma en una lista de argumentos no es el operador paralelo descrito anteriormente;
Puede inicializar una declinación de matriz:
Puede hacer una llamada a malloc / calloc / sbrk / alloca / etc para asignar una región fija de almacenamiento a un objeto:
y acceder a los miembros por:
Etc.
fuente