¿Cómo inicializar todos los miembros de una matriz con el mismo valor?
Tengo una matriz grande en C (no en C++ si eso marca la diferencia). Quiero inicializar todos los miembros del mismo valor.
Podría jurar que una vez conocí una forma sencilla de hacer esto. Podría usarlo memset()
en mi caso, pero ¿no hay una manera de hacerlo que esté integrada directamente en la sintaxis de C?
A menos que ese valor sea 0 (en cuyo caso puede omitir alguna parte del inicializador y los elementos correspondientes se inicializarán en 0), no hay una manera fácil.
Sin embargo, no pase por alto la solución obvia:
int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
Los elementos con valores faltantes se inicializarán a 0:
int myArray[10] = { 1, 2 }; // initialize to 1,2,0,0,0...
Entonces esto inicializará todos los elementos a 0:
int myArray[10] = { 0 }; // all elements 0
En C++, una lista de inicialización vacía también inicializará cada elemento a 0. Esto no está permitido con C hasta C23:
int myArray[10] = {}; // all elements 0 in C++ and C23
Recuerde que los objetos con duración de almacenamiento estático se inicializarán en 0 si no se especifica ningún inicializador:
static int myArray[10]; // all elements 0
Y ese "0" no significa necesariamente "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 un valor nulo, etc.)
Si su compilador es GCC, puede utilizar la siguiente sintaxis de "extensión GNU":
int array[1024] = {[0 ... 1023] = 5};
Consulte la descripción detallada: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html
Para inicializar estáticamente una matriz grande con el mismo valor, sin copiar y pegar varias veces, puede usar macros:
#define VAL_1X 42
#define VAL_2X VAL_1X, VAL_1X
#define VAL_4X VAL_2X, VAL_2X
#define VAL_8X VAL_4X, VAL_4X
#define VAL_16X VAL_8X, VAL_8X
#define VAL_32X VAL_16X, VAL_16X
#define VAL_64X VAL_32X, VAL_32X
int myArray[53] = { VAL_32X, VAL_16X, VAL_4X, VAL_1X };
Si necesita cambiar el valor, debe realizar el reemplazo en un solo lugar.
Editar: posibles extensiones útiles
(cortesía de Jonathan Leffler )
Puedes generalizar esto fácilmente con:
#define VAL_1(X) X
#define VAL_2(X) VAL_1(X), VAL_1(X)
/* etc. */
Se puede crear una variante usando:
#define STRUCTVAL_1(...) { __VA_ARGS__ }
#define STRUCTVAL_2(...) STRUCTVAL_1(__VA_ARGS__), STRUCTVAL_1(__VA_ARGS__)
/*etc */
que funciona con estructuras o matrices compuestas.
#define STRUCTVAL_48(...) STRUCTVAL_32(__VA_ARGS__), STRUCTVAL_16(__VA_ARGS__)
struct Pair { char key[16]; char val[32]; };
struct Pair p_data[] = { STRUCTVAL_48("Key", "Value") };
int a_data[][4] = { STRUCTVAL_48(12, 19, 23, 37) };
Los nombres de las macros son negociables.
Si desea asegurarse de que cada miembro de la matriz se inicialice explícitamente, simplemente omita la dimensión de la declaración:
int myArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
El compilador deducirá la dimensión de la lista de inicializadores. Desafortunadamente, para matrices multidimensionales sólo se puede omitir la dimensión más externa:
int myPoints[][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
está bien, pero
int myPoints[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
no es.
Vi un código que usaba esta sintaxis:
char* array[] =
{
[0] = "Hello",
[1] = "World"
};
Donde se vuelve particularmente útil es si estás creando una matriz que usa enumeraciones como índice:
enum
{
ERR_OK,
ERR_FAIL,
ERR_MEMORY
};
#define _ITEM(x) [x] = #x
char* array[] =
{
_ITEM(ERR_OK),
_ITEM(ERR_FAIL),
_ITEM(ERR_MEMORY)
};
Esto mantiene las cosas en orden, incluso si escribe algunos de los valores de enumeración fuera de orden.
Puede encontrar más información sobre esta técnica aquí y aquí .