2012-03-05 10 views
15

Sé en C que puedo hacer lo siguiente.Inicialización de la matriz C en otro momento que no sea la declaración?

int test[5] = {1, 2, 3, 4, 5}; 

Ahora esto solo es legal al declarar la matriz. Sin embargo, me preguntaba por qué esto no es legal para hacer más tarde. Pero luego, más adelante en el programa, no es legal hacer lo siguiente.

test[5] = {10, 20, 30, 40, 50}; 

O algo similar. ¿Por qué es esto? Sé que no es legal, y no me estoy quejando, pero ¿podría alguien darme una explicación más técnica de por qué no puedo hacer esto? (es decir, no digas que la especificación C no lo permite o algo así)

Supongo que tiene que hacer algo con el tiempo cuando la memoria se asigna en la pila para la matriz, por lo que en ese punto C puede completar automáticamente mis valores, pero ¿por qué no puede hacerlo más tarde?

Gracias chicos

+2

Así que si, hipotéticamente, que era el caso de que el estándar de C no permitiría que esto (aunque sería técnicamente posible), tendríamos que hacer algo diferente en su lugar? ¿O prefieres no obtener una respuesta? Solo quiero estar seguro. –

+1

@NiklasB .: Supongo que en ese caso una conjetura bien argumentada sobre * por qué * los diseñadores del lenguaje C decidieron omitir esta característica estaría bien como respuesta. – Heinzi

+0

@Heinzi: Oh, veo :) –

Respuesta

6

El punto es que el uso de int array[]={ } es declarar y inicializar el objeto que ha creado.

Puede realidad asigna valores en una matriz después que se ha declaró:

int array[5]; 
array[0] = 1, array[1] = 2, ... 

Lo que estaba haciendo estaba asignando varios valores a uno sola entrada de la matriz:

array[5] = {1,2,3,4,5}; // array[5] can only contain one value 

This wo uld sea legal en su lugar:

array[5] = 6; 

Espero que esto tenga sentido. Solo una cuestión de sintaxis.

+0

Oh. Duhhh. Esto realmente me ayudó. – kando

17

No son solo las matrices, no puede proporcionar un inicializador para nada en cualquier punto que no sea en una definición. La gente a veces se refiere a la segunda declaración de algo como int i; i = 0; como "inicializando i". De hecho, está asignando a i, que anteriormente tiene un valor indeterminado porque no se inicializó. Raramente es confuso llamar a esto "inicialización", pero en lo que se refiere al lenguaje, no hay inicializador allí.

La asignación y la inicialización son cosas separadas del lenguaje, aunque ambos usan el carácter =. Las matrices no son asignables.

El motivo por el que no se pueden asignar matrices está cubierto en otra parte, por ejemplo Why does C++ support memberwise assignment of arrays within structs, but not generally?. La respuesta corta es "razones históricas". No creo que exista ninguna razón técnica determinante por la que no se pueda cambiar el idioma para permitir la asignación de conjuntos.

Hay un problema secundario, que gramaticalmente {1, 2, 3, 4, 5} es un inicializador, no una matriz literal, y por lo tanto no se puede usar en la asignación, incluso si las matrices son asignables. No estoy seguro de por qué C89 no tiene literales de arreglos, probablemente nadie los haya necesitado. C99 introduce una sintaxis para "literales compuestos" en general y literales de arreglos en particular: (int[]) {1, 2, 3, 4, 5}.Aún no puede asignarle una matriz.

3

Tenga en cuenta que el compuesto C99 literal le permite 'pasar matrices a funciones':

int your_func(int *test) 
{ 
    ...use test as an array... 
} 

void other_func(void) 
{ 
    int x = rand(); 
    if (your_func((int[]){ 0, 1, 2, x, 3, 4 }) > 0 || 
     your_func((int[]){ 9, x, 8, 7, 6, 5 }) > 0) 
     ...whatever... 
} 

Ésta no es la misma que la re-inicialización de una matriz con valores diferentes, pero puede ser lo suficientemente cerca para que funciona para ti

0

La razón de esto en la superficie es que las matrices se convierten casi en todas partes en un puntero al primer elemento. Si tiene dos matrices

double A[5]; 
double B[5]; 

en una expresión como

A = B; 

ambos ya se convierten en punteros. El A a la izquierda no es en particular un "lvalue", por lo que no se puede asignar.

Esto suena como una excusa poco convincente, pero mi suposición es que históricamente simplemente sucedió así. C (y C++ con él) quedaron atrapados en una elección de sintaxis temprana y, si quieres seguir siendo compatible con el código heredado, probablemente no haya mucho para salir de él.

+0

¿Tiene alguna cita de que esta fue la razón detrás de la decisión de diseño? –

+0

@DavidHeffernan, desafortunadamente no, de lo contrario lo habría dado. En C11, 6.7.1 p6 (más nota al pie) todavía muestra que esta obligación de convertir a un puntero se toma como característica muy básica de las matrices. Creo que esto es desafortunado, en particular la asignación y los designadores serían buenas características. Pero sería poco realista esperar que ocurra tal modificación. –

+0

Pero sin citas, esto es especulación. Y no puedo ver una razón técnica por la cual la asignación de arrays no pudo ser implementada. –

2

Aquí está la solución

//Declaration 
int a[5]; 
int a_temp[5] = {1, 2, 3, 4, 5 }; 
memcpy(a, a_temp, sizeof(a)); 
//Now array a have values 1, 2, 3, 4, 5 
Cuestiones relacionadas