strings - Declarar e inicializar arrays en C
matriz de caracteres en c (8)
¿Hay una manera de declarar primero y luego inicializar una matriz en C?
Hasta ahora he estado inicializando una matriz como esta:
int myArray[SIZE] = {1,2,3,4....};
Pero necesito hacer algo como esto
int myArray[SIZE];
myArray = {1,2,3,4....};
¿Hay una manera de declarar primero y luego inicializar una matriz en C?
¡Ahi esta! Pero no utilizando el método que describiste.
No se puede inicializar con una lista separada por comas, esto solo se permite en la declaración. Sin embargo, puedes inicializar con ...
myArray[0] = 1;
myArray[1] = 2;
...
o
for(int i = 1; i <= SIZE; i++)
{
myArray[i-1] = i;
}
¿Por qué no puedes inicializar cuando declaras?
¿Qué compilador de C estás usando? ¿Es compatible con C99?
Si es compatible con C99, puede declarar la variable donde la necesita e inicializarla cuando la declara.
La única excusa que se me ocurre para no hacerlo es porque necesita declararlo pero antes de usarlo antes de usarlo, por lo que se desperdiciaría el inicializador. Sin embargo, sospecho que cualquier código de este tipo no está tan bien organizado como debería y podría estar escrito, por lo que no fue un problema.
El OP omitió cierta información crucial de la pregunta y solo la incluyó en un comentario o una respuesta.
Necesito inicializar después de declarar, porque será diferente dependiendo de una condición, quiero decir algo como esto int myArray [TAMAÑO]; if (condition1) {myArray {x1, x2, x3, ...}} else if (condition2) {myArray {y1, y2, y3, ...}}. . y así...
Teniendo esto en cuenta, todas las matrices posibles deberán almacenarse en datos en algún lugar, por lo que no se necesita memoria (o se desea), solo se requiere un puntero y una matriz 2D.
//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 incorporada proporciona este ensamblaje 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 obtener más condicionales / matrices, simplemente cambie el 2 en myArrays al número deseado y use una lógica similar para obtener un puntero a la matriz correcta.
En C99 puedes hacerlo usando un literal compuesto 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 del objetivo sea el mismo).
En C89 / 90 puede emular eso declarando una matriz "fuente" adicional
const int SOURCE[SIZE] = { 1, 2, 3, 4 }; /* maybe `static`? */
int myArray[SIZE];
...
memcpy(myarray, SOURCE, sizeof myarray);
Este es un addendum a la respuesta aceptada por AndreyT, con el comentario de Nyan sobre tamaños de matrices no coincidentes. No estoy de acuerdo con su configuración automática del quinto elemento a cero. Probablemente debería ser 5 - el número después de 1,2,3,4. Por lo tanto, sugeriría un envoltorio a memcpy () para producir un error de tiempo de compilación cuando intentemos 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. Lo que quizás sea una característica.
Debido a que estamos utilizando una macro, el literal compuesto de C99 parece necesitar un par de paréntesis adicionales:
Memcpy(myarray, ((int[]) { 1, 2, 3, 4 }));
Aquí ASSERT () es un ''assert estático''. Si aún no tienes el tuyo, uso lo siguiente en varias 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)}
No es posible asignar valores a una matriz de una vez después de la inicialización. La mejor alternativa sería usar un bucle.
for(i=0;i<N;i++)
{
array[i] = i;
}
Puede codificar y asignar valores como - array[0] = 1
y así sucesivamente.
Memcpy también se puede usar si ya tiene los datos almacenados en una matriz.
No existe una forma tan particular en la que pueda inicializar la matriz después de declararla una vez.
Hay tres opciones solamente:
1.) Inicializarlos 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 quieres, supongo.
2.) Inicialícelos usando un bucle for o while:
for (i = 0; i < MAX ; i++) {
array[i] = i;
}
Esta es la MEJOR MANERA de lograr tu objetivo.
3.) En caso de que su requerimiento sea inicializar la matriz en una sola 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 ningún beneficio al hacerlo, en ese caso, debe definir e inicializar su matriz en una sola línea.
¿Y puedo preguntarte por qué específicamente quieres hacerlo?
No, no puede establecerlos en valores arbitrarios en una declaración (a menos que se haga como parte de la declaración).
Puedes hacerlo con código, algo 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 alrededor de algunas plantillas que se configuran en el momento de la declaración y usarlas 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 en las que tengo que reinicializar una matriz rápidamente pero a un estado específico (si el estado fuera todo de ceros, solo usaría memset
).
Incluso puedes localizarlo en 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 con toda seguridad) se creará en el momento de la compilación, por lo que no habrá costo en tiempo de ejecución para eso, y el memcpy
debería ser cegadoramente rápido, probablemente más rápido que 1,229 declaraciones de asignación, pero definitivamente menos escritura de su parte :-) .