¿Cómo inicializar todos los miembros de una matriz al mismo valor?


Tengo una matriz grande en C (no C++ si eso hace una diferencia). Quiero inicializar todos los miembros al mismo valor. Juraría que una vez supe una manera sencilla de hacer esto. Podría usar memset() en mi caso, pero ¿no hay una forma de hacer esto que esté integrada en la sintaxis de C?

Author: Lundin, 2008-10-14

18 answers

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.

No pase por alto la solución obvia, sin embargo:

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...

Así que 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ático se inicializarán a 0 si no se especifica el inicializador:

static int myArray[10]; // all elements 0

Y que " 0 "no significa necesariamente" todos-bits-cero", por lo que usar lo anterior es mejor y más portátil que memset(). (Los valores de coma flotante serán inicializado a +0, punteros a valor nulo, etc.)

 1056
Author: aib,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:33:24

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

 352
Author: qrdl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-13 22:43:06

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, tiene que hacer el reemplazo en un solo lugar.

Editar: posibles extensiones útiles

(cortesía de Jonathan Leffler)

Puede 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 trabaja con estructuras o compuesto matriz.

#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 macro son negociables.

 163
Author: mouviciel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:36

Si desea asegurarse de que cada miembro de la matriz está explícitamente inicializado, 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 inicializador. Desafortunadamente, para arreglos 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 lo es.

 59
Author: Frank Szczerba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-14 18:30:25

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 se escriben algunos de los valores de enumeración fuera de orden.

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

 45
Author: abelenky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-22 18:34:31
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
Author: Tarski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-14 13:34:02

Puede hacer todo el inicializador estático como se detalla anteriormente, pero puede ser un verdadero fastidio cuando el tamaño de su matriz cambia (cuando su matriz embiggens, si no agrega los inicializadores adicionales apropiados, obtiene basura).

Memset le da un golpe en tiempo de ejecución para hacer el trabajo, pero ningún golpe de tamaño de código hecho correctamente es inmune a los cambios de tamaño de matriz. Usaría esta solución en casi todos los casos cuando la matriz era más grande que, digamos, unas pocas docenas de elementos.

Si fuera realmente importante que la matriz se declaró estáticamente, me gustaría escribir un programa para escribir el programa para mí y hacerlo parte del proceso de construcción.

 11
Author: plinth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-14 13:29:25

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},
};

Véase:

C-Extensions

Designados inits

Entonces haz la pregunta: ¿Cuándo se pueden usar extensiones C?

El ejemplo de código anterior está en un sistema embebido y nunca verá la luz de otro compilador.

 8
Author: humble_guru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-27 08:04:06

Para inicializar tipos de datos' normales '(como los arrays int), puede usar la notación de corchetes, pero pondrá a cero los valores después del último si todavía hay espacio en el array:

// put values 1-8, then two zeroes
int list[10] = {1,2,3,4,5,6,7,8};
 5
Author: warren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-14 13:17:39

Una respuesta ligeramente irónica; escriba la declaración

array = initial_value

En tu lenguaje favorito compatible con array (el mío es Fortran, pero hay muchos otros), y enlázalo a tu código C. Probablemente quieras envolverlo para que sea una función externa.

 5
Author: High Performance Mark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-27 08:06:18

Si el array resulta ser int o cualquier cosa con el tamaño de int o el tamaño de su mem-pattern encaja 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 moviendo el índice.

 4
Author: ddimitrov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-25 12:43:00

Hay una forma rápida de inicializar una matriz de cualquier tipo con un valor dado. Funciona muy bien con arreglos grandes. El algoritmo es el siguiente:

  • inicializar el primer elemento de la matriz (forma habitual)
  • copie la parte que se ha establecido en la parte que no se ha establecido, duplicando el tamaño con cada operación de copia siguiente

For 1 000 000 elements int array it is 4 times faster than regular loop initialization (i5, 2 cores, 2.3 GHz, 4GiB memory, 64 bits):

loop runtime 0.004248 [seconds]

memfill() runtime 0.001085 [seconds]


#include <stdio.h>
#include <time.h>
#include <string.h>
#define ARR_SIZE 1000000

void memfill(void *dest, size_t destsize, size_t elemsize) {
   char   *nextdest = (char *) dest + elemsize;
   size_t movesize, donesize = elemsize;

   destsize -= elemsize;
   while (destsize) {
      movesize = (donesize < destsize) ? donesize : destsize;
      memcpy(nextdest, dest, movesize);
      nextdest += movesize; destsize -= movesize; donesize += movesize;
   }
}    
int main() {
    clock_t timeStart;
    double  runTime;
    int     i, a[ARR_SIZE];

    timeStart = clock();
    for (i = 0; i < ARR_SIZE; i++)
        a[i] = 9;    
    runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
    printf("loop runtime %f [seconds]\n",runTime);

    timeStart = clock();
    a[0] = 10;
    memfill(a, sizeof(a), sizeof(a[0]));
    runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
    printf("memfill() runtime %f [seconds]\n",runTime);
    return 0;
}
 3
Author: Maciej,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-03 11:59:20

Nadie ha mencionado el orden del índice para acceder a los elementos del array inicializado. Mi código de ejemplo le dará un ejemplo ilustrativo.

#include <iostream>

void PrintArray(int a[3][3])
{
    std::cout << "a11 = " << a[0][0] << "\t\t" << "a12 = " << a[0][1] << "\t\t" << "a13 = " << a[0][2] << std::endl;
    std::cout << "a21 = " << a[1][0] << "\t\t" << "a22 = " << a[1][1] << "\t\t" << "a23 = " << a[1][2] << std::endl;
    std::cout << "a31 = " << a[2][0] << "\t\t" << "a32 = " << a[2][1] << "\t\t" << "a33 = " << a[2][2] << std::endl;
    std::cout << std::endl;
}

int wmain(int argc, wchar_t * argv[])
{
    int a1[3][3] =  {   11,     12,     13,     // The most
                        21,     22,     23,     // basic
                        31,     32,     33  };  // format.

    int a2[][3] =   {   11,     12,     13,     // The first (outer) dimension
                        21,     22,     23,     // may be omitted. The compiler
                        31,     32,     33  };  // will automatically deduce it.

    int a3[3][3] =  {   {11,    12,     13},    // The elements of each
                        {21,    22,     23},    // second (inner) dimension
                        {31,    32,     33} };  // can be grouped together.

    int a4[][3] =   {   {11,    12,     13},    // Again, the first dimension
                        {21,    22,     23},    // can be omitted when the 
                        {31,    32,     33} };  // inner elements are grouped.

    PrintArray(a1);
    PrintArray(a2);
    PrintArray(a3);
    PrintArray(a4);

    // This part shows in which order the elements are stored in the memory.
    int * b = (int *) a1;   // The output is the same for the all four arrays.
    for (int i=0; i<9; i++)
    {
        std::cout << b[i] << '\t';
    }

    return 0;
}

La salida es:

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

11      12      13      21      22      23      31      32      33
 2
Author: hkBattousai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-22 07:58:43
  1. Si su matriz se declara como estática o es global, todos los elementos en la matriz ya tienen valor predeterminado por defecto 0.
  2. Algunos compiladores establecen el array por defecto a 0 en modo de depuración.
  3. Es fácil establecer el valor predeterminado en 0 : matriz int[10] = {0};
  4. Sin embargo, para otros valores, tiene que usar memset() o loop;

Ejemplo: matriz int[10]; memset (array, -1, 10 *sizeof (int));

 1
Author: Hannah Zhang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-29 01:21:32

Cortando todo el chatter, la respuesta corta es que si activa la optimización en tiempo de compilación, no lo hará mejor que esto:

int i,value=5,array[1000]; 
for(i=0;i<1000;i++) array[i]=value; 

Bono añadido: el código es realmente legible:)

 1
Author: JWDN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-05 16:12:23
#include<stdio.h>
int main(){
int i,a[50];
for (i=0;i<50;i++){
    a[i]=5;// set value 5 to all the array index
}
for (i=0;i<50;i++)
printf("%d\n",a[i]);
   return 0;
}

Dará el o/p 5 5 5 5 5 5 ...... hasta el tamaño de toda la matriz

 0
Author: Dadhich Sourav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-26 09:05:14

Sé que el usuario Tarski respondió a esta pregunta de manera similar, pero agregué algunos detalles más. Perdona algo de mi C porque estoy un poco oxidado ya que estoy más inclinado a querer usar C++, pero aquí va.


Si conoce el tamaño del array antes de tiempo...

#include <stdio.h>

typedef const unsigned int cUINT;
typedef unsigned int UINT;

cUINT size = 10;
cUINT initVal = 5;

void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal );
void printArray( UINT* myArray ); 

int main() {        
    UINT myArray[size]; 
    /* Not initialized during declaration but can be
    initialized using a function for the appropriate TYPE*/
    arrayInitializer( myArray, size, initVal );

    printArray( myArray );

    return 0;
}

void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal ) {
    for ( UINT n = 0; n < size; n++ ) {
        myArray[n] = initVal;
    }
}

void printArray( UINT* myArray ) {
    printf( "myArray = { " );
    for ( UINT n = 0; n < size; n++ ) {
        printf( "%u", myArray[n] );

        if ( n < size-1 )
            printf( ", " );
    }
    printf( " }\n" );
}

Hay algunas advertencias anteriores; una es que UINT myArray[size]; no se inicializa directamente en la declaración, sin embargo, el siguiente bloque de código o llamada a función inicializa cada elemento de la matriz a la el mismo valor que quieres. La otra advertencia es que tendría que escribir un initializing function para cada type que soportará y también tendría que modificar la función printArray() para soportar esos tipos.


Puede probar este código con un complier en línea encontrado aquí.

 0
Author: Francis Cugler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-28 19:46:56

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:

#include <string.h> 

void array_init( void *start, size_t element_size, size_t elements, void *initval ){
  memcpy(        start,              initval, element_size              );
  memcpy( (char*)start+element_size, start,   element_size*(elements-1) );
}

// testing
#include <stdio.h> 

struct s {
  int a;
  char b;
} array[2][3], init;

int main(){
  init = (struct s){.a = 3, .b = 'x'};
  array_init( array, sizeof(array[0][0]), 2*3, &init );

  for( int i=0; i<2; i++ )
    for( int j=0; j<3; j++ )
      printf("array[%i][%i].a = %i .b = '%c'\n",i,j,array[i][j].a,array[i][j].b);
}

Resultado:

array[0][0].a = 3 .b = 'x'
array[0][1].a = 3 .b = 'x'
array[0][2].a = 3 .b = 'x'
array[1][0].a = 3 .b = 'x'
array[1][1].a = 3 .b = 'x'
array[1][2].a = 3 .b = 'x'

EDITAR: start+element_size cambiado a (char*)start+element_size

 -1
Author: sambowry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-10-14 11:12:00