Pregunta ¿Cómo inicializar todos los miembros de una matriz con el mismo valor?


Tengo una gran matriz en C (no C ++ si eso hace la diferencia). Quiero inicializar todos los miembros con el mismo valor. Juraría que una vez conocí una forma simple de hacer esto. Podría usar memset() en mi caso, pero ¿no hay una forma de hacer esto que está integrada en la sintaxis C?


789
2017-10-14 13:13


origen


Respuestas:


A menos que ese valor sea 0 (en cuyo caso puede omitir una 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:

int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };

Los elementos con valores faltantes se inicializarán en 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 es No permitido con C:

int myArray[10] = {}; // all elements 0 in C++

Recuerde que los objetos con duración de almacenamiento estática se inicializarán a 0 si no Se especifica el 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 punto flotante serán inicializado a +0, punteros a valores nulos, etc.)


1028
2017-10-14 13:17



Si su compilador es GCC, puede usar la siguiente sintaxis:

int array[1024] = {[0 ... 1023] = 5};

Echa un vistazo a la descripción detallada: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html


348
2017-10-16 07:38



Para inicializar estáticamente una matriz grande con el mismo valor, sin copiar y pegar múltiples, 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 reemplazarlo en un solo lugar.

Editar: posibles extensiones útiles

(cortesía de Jonathan Leffler)

Puedes generalizar fácilmente esto 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 macro son negociables.


161
2017-10-14 10:27



Si desea asegurarse de que cada miembro de la matriz esté inicializado 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 las matrices multidimensionales solo 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.


59
2017-10-14 18:30



Vi un código que usaba esta sintaxis:

char* array[] = 
{
    [0] = "Hello",
    [1] = "World"
};   

Donde se vuelve particularmente útil es si estás haciendo 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 enum fuera de servicio.

Se puede encontrar más sobre esta técnica aquí y aquí.


45
2018-03-21 21:02



int i;
for (i = 0; i < ARRAY_SIZE; ++i)
{
  myArray[i] = VALUE;
}

Creo que esto es mejor que

int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5...

en caso de que cambie el tamaño de la matriz.


22
2017-10-14 13:34



Puedes hacer todo el proceso de inicialización estática como se detalla más arriba, pero puede ser una verdadera molestia cuando el tamaño de tu matriz cambia (cuando tu matriz se embigra, si no agregas los inicializadores extra apropiados, obtienes basura).

memset te da un golpe de tiempo de ejecución por hacer el trabajo, pero ningún golpe de tamaño de código hecho a la derecha es inmune a los cambios en el tamaño de la matriz. Usaría esta solución en casi todos los casos cuando la matriz fuera más grande que, por ejemplo, unas pocas docenas de elementos.

Si era realmente importante que la matriz estuviera declarada estáticamente, escribiría un programa para escribir el programa y convertirlo en parte del proceso de compilación.


11
2017-10-14 13:29



Aquí hay otra manera:

static void
unhandled_interrupt(struct trap_frame *frame, int irq, void *arg)
{
    //this code intentionally left blank
}

static struct irqtbl_s vector_tbl[XCHAL_NUM_INTERRUPTS] = {
    [0 ... XCHAL_NUM_INTERRUPTS-1] {unhandled_interrupt, NULL},
};

Ver:

C-Extensiones

Designado inits

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.


8
2017-10-14 22:12