2010-06-29 109 views
48

¿Hay alguna manera de declarar primero y luego inicializar una matriz en C?Declaración e inicialización de matrices en C

Hasta ahora se han inicializar una matriz de la siguiente manera:

int myArray[SIZE] = {1,2,3,4....}; 

pero tengo que hacer algo como esto

int myArray[SIZE]; 

myArray = {1,2,3,4....}; 

Respuesta

28

En C99 que puede hacerlo usando un compuesto literal en combinación con memcpy

memcpy(myarray, (int[]) { 1, 2, 3, 4 }, sizeof myarray); 

(suponiendo que el tamaño de la fuente y el tamaño de la diana es la misma).

En C89/90, se puede emular al declarar que un adicional de "fuente" matriz

const int SOURCE[SIZE] = { 1, 2, 3, 4 }; /* maybe `static`? */ 
int myArray[SIZE]; 
... 
memcpy(myarray, SOURCE, sizeof myarray); 
+3

Diría * definitivamente * 'estático'. – caf

+0

Creo que la forma más conveniente en mi caso, en lugar de asignar cada elemento, copie cada matriz deseada en una matriz global. Muchas gracias –

+1

+1 por C99. ;) memcpy (myarray, (int [sizeof (myarray)/sizeof (myarray [0])] {1,2,3,4}, sizeof myarray); para iniciar el resto en el cero apropiado. – Nyan

1

Por qué no puedes inicializar cuando se declara?

Qué compilador de C está usando? ¿Es compatible con C99?

Si es compatible con C99, se puede declarar la variable donde se lo necesita y lo inicializa cuando se declara.

La única excusa que se me ocurre por no hacer lo que sería debido a que tienen que declarar, pero hace una salida temprana antes de usarlo, por lo que el inicializador se desperdiciaría. Sin embargo, sospecho que dicho código no está tan bien organizado como debería y podría escribirse para que no haya ningún problema.

+0

¡Gracias por la respuesta rápida! Necesito inicializar después de declarar, porque será diferente dependiendo de una condición, quiero decir algo como esto int myArray [SIZE]; si (condición1) { miMatriz {x1, x2, x3, ...} } else if (condición2) { miMatriz {y1, y2, y3, ...}} . . y así sucesivamente. Estoy usando XCode –

+1

¿Las matrices son constantes? Si es así, una posibilidad es usar dos matrices de constante inicializadas separadas, y luego establecer un puntero (a datos constantes) para apuntar a la matriz relevante. También haría las matrices estáticas. Si las matrices no son constantes, entonces creo que estás atascado con el cálculo de cada elemento por turno. –

+0

Sí, las matrices son constantes, voy a probar este método también, gracias. –

4

¿Hay una manera de declarar primero y luego inicializar una matriz en C?

No! pero no usando el método que describiste

No se puede inicializar con una lista separada por comas, esto sólo está permitido en la declaración. Sin embargo, puede inicializar con ...

myArray[0] = 1; 
myArray[1] = 2; 
... 

o

for(int i = 1; i <= SIZE; i++) 
{ 
    myArray[i-1] = i; 
} 
+1

Gracias, pero lo que estaba buscando porque fue capaz de inicializarlo en una lista separada por comas, porque esas matrices serán muy grandes y pensé que sería más conveniente de esa manera. –

13

No, no podrá ajustar a valores arbitrarios en una declaración (a no ser hecho como parte de la declaración).

Usted puede hacerlo con código, algo así como:

myArray[0] = 1; 
myArray[1] = 2; 
myArray[2] = 27; 
: 
myArray[99] = -7; 

o (si hay una fórmula):

for (int i = 0; i < 100; i++) myArray[i] = i + 1; 

La otra posibilidad es mantener en torno a algunas plantillas que son establecer en el momento de la declaración y usarlos para inicializar su matriz, algo como:

static const int onceArr[] = { 0, 1, 2, 3, 4,..., 99}; 
static const int twiceArr[] = { 0, 2, 4, 6, 8,...,198}; 
: 
int myArray[7]; 
: 
memcpy (myArray, twiceArr, sizeof (myArray)); 

Esto tiene la ventaja de que (lo más probable) es más rápido y le permite crear matrices más pequeñas que las plantillas.He usado este método en situaciones donde tengo que reinicializar una matriz rápidamente pero a un estado específico (si el estado fuera todo ceros, simplemente usaría memset).


Incluso se puede localizar a una función de inicialización:

void initMyArray (int *arr, size_t sz) { 
    static const int template[] = {2, 3, 5, 7, 11, 13, 17, 19, 21, ..., 9973}; 
    memcpy (arr, template, sz); 
} 
: 
int myArray[100]; 
initMyArray (myArray, sizeof(myArray)); 

La matriz estática (casi seguro) se creará en tiempo de compilación por lo que no habrá ningún costo en tiempo de ejecución para eso, y el memcpy debe ser deslumbrantemente rápido, probablemente más rápido que 1,229 declaraciones de asignación pero definitivamente menos tipeado de su parte :-).

0

No existe una manera particular de inicializar la matriz después de declararla una vez.

hay tres opciones: sólo

1.) ellos initialize en diferentes líneas:

int array[SIZE]; 

array[0] = 1; 
array[1] = 2; 
array[2] = 3; 
array[3] = 4; 
//... 
//... 
//... 

pero eso no es lo que quiere, supongo.

2.) inicializarlas utilizando un bucle for o while:

for (i = 0; i < MAX ; i++) { 
    array[i] = i; 
} 

Esta es la mejor manera por la manera de lograr su objetivo.

3.) En caso de que su necesidad sea inicializar la matriz en una línea, debe definir al menos una matriz con inicialización. Y luego cópielo a su matriz de destino, pero creo que no hay beneficio de hacerlo, en ese caso debe definir e inicializar su matriz en una línea.

¿Y puedo preguntarte por qué específicamente quieres hacerlo?

2

Este es un apéndice a la respuesta aceptada por AndreyT, con el comentario de Nyan sobre tamaños de matriz no coincidentes. No estoy de acuerdo con su configuración automática del quinto elemento a cero. Probablemente sea --el número después de 1,2,3,4. Así que yo sugeriría un envoltorio a memcpy() para producir un tiempo de compilación de error cuando se intenta copiar matrices de diferentes tamaños:

#define Memcpy(a,b) do {     /* copy arrays */  \ 
    ASSERT(sizeof(a) == sizeof(b) &&  /* a static assert */ \ 
      sizeof(a) != sizeof((a) + 0)); /* no pointers */  \ 
    memcpy((a), (b), sizeof (b));   /* & unnecesary */  \ 
    } while (0)        /* no return value */ 

Esta macro generará un error en tiempo de compilación si la matriz es de longitud 1. Cuál es quizás una característica.

Debido a que estamos utilizando una macro, el compuesto C99 literal parece necesitar un par extra de paréntesis:

Memcpy(myarray, ((int[]) { 1, 2, 3, 4 })); 

Aquí ASSERT() es un 'afirman estática'. Si aún no dispone de su propia, que utilice la siguiente en una serie de plataformas:

#define CONCAT_TOKENS(a, b) a ## b 
#define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b) 
#define ASSERT(e) enum {EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)} 
#define ASSERTM(e,m) /* version of ASSERT() with message */ \ 
    enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)} 
0

El PO queda algo de información fundamental de la cuestión y sólo ponerlo en un comentario a una respuesta.

se tiene que inicializar después de declarar, ya que será diferente dependiendo de una condición, me refiero a algo como esto int miMatriz [TAMAÑO]; if (condition1) {myArray {x1, x2, x3, ...}} else if (condition2) {myArray {y1, y2, y3, ...}}. . y así sucesivamente ...

Con esto en mente, todas las posibles matrices tendrá que ser almacenado en algún lugar de datos de todos modos, por lo que no se necesita ningún establecimiento de memoria (o deseado), solamente un puntero y una matriz 2D son necesario.

//static global since some compilers build arrays from instruction data 
//... notably not const though so they can later be modified if needed 
#define SIZE 8 
static int myArrays[2][SIZE] = {{0,1,2,3,4,5,6,7},{7,6,5,4,3,2,1,0}}; 

static inline int *init_myArray(_Bool conditional){ 
    return myArrays[conditional]; 
} 

// now you can use: 
//int *myArray = init_myArray(1 == htons(1)); //any boolean expression 

La versión no-inline da este conjunto resultante en x86_64:

init_myArray(bool): 
     movzx eax, dil 
     sal  rax, 5 
     add  rax, OFFSET FLAT:myArrays 
     ret 
myArrays: 
     .long 0 
     .long 1 
     .long 2 
     .long 3 
     .long 4 
     .long 5 
     .long 6 
     .long 7 
     .long 7 
     .long 6 
     .long 5 
     .long 4 
     .long 3 
     .long 2 
     .long 1 
     .long 0 

Para condicionales/matrices adicionales, simplemente cambiar el 2 en myArrays al número deseado y utilizar una lógica similar para obtener un puntero a la matriz correcta.

+0

[Ver este hilo] (http://stackoverflow.com/questions/6312597/is-inline-without-static-or-extern-ever-useful-in-c99) para obtener más información sobre el uso de 'inline' –

+0

@M.M el en línea aquí es más sobre intención que otra cosa, realmente no necesita ser una función en absoluto, pero no tengo un compilador para escupir ensamblado para código que no está contenido en una función – technosaurus

+0

Sí, yo acabo de proporcionar ese enlace para beneficio de cualquiera que quiera incorporar esto en un programa, ya que el uso correcto de 'en línea' no es intuitivo en el Estándar C –

0

No es posible asignar valores a una matriz todos a la vez después de la inicialización. La mejor alternativa sería usar un bucle.

for(i=0;i<N;i++) 
{ 
    array[i] = i; 
} 

que puede codificar y asignar valores como - array[0] = 1 y así sucesivamente.

Memcpy también se puede utilizar si ya tiene los datos almacenados en una matriz.

Cuestiones relacionadas