2009-04-27 31 views
5

Lo siento si esto es una cuestión novato :(¡Demasiados elementos en una matriz! ..?!

pedazo de código en C

int array[5]; 
int cnt; 

for(cnt = 0; cnt <= 10; cnt+=1) 
{ 
     array[cnt] = cnt; 
} 

debe dar un error, a la derecha no funciona bien Pero ¿por qué es que parece que!? - en la primera línea, se define una matriz de más del tamaño doble (11). Incluso puede acceder a la matriz [5 a 10] más adelante. Y eso me confunde. Deja de funcionar cuando define una matriz [4 o menos] ...

Gracias de antemano

Respuesta

23

Puede funcionar con su compilador y computadora en particular, pero no debe contar con él.

El comportamiento de su código según la especificación del lenguaje C es undefined. Esto significa que podría hacer lo que usted espera, o podría hacer que su computadora se bloquee, o podría causar demons to fly out your nose.

A diferencia de los lenguajes de nivel superior como Java y C#, C confía en usted y no realiza comprobaciones explícitas en los límites de las matrices. Se supone que eres responsable y no pisas fuera de los límites de la matriz.

+3

+1 para la defensa del demonio nasal! – RBerteig

+2

@RBerteig: No creo que "defenestración" (la defensa no es una palabra) significa lo que piensas que significa. En inglés, ese sería el acto de arrojar a alguien/algo a través de una ventana. http://en.wikipedia.org/wiki/Defenestration –

+0

Un error tipográfico, de hecho, pero la elección de la palabra fue deliberada. Estaba buscando algo que aliterara con "demonio" que tenía la cantidad correcta de una sensación de expulsión inesperada. Fue un tramo, y posiblemente más allá del punto de ruptura de la metáfora ;-) – RBerteig

4

"¿Pero por qué es eso?"

Porque así es C.

Los límites de la matriz no se verifican en el tiempo de ejecución.

Esa es la "Ley de la C"

16

Esto sólo "funciona" si su definición de "obras" es sinónimo de "no ha desplomado aún".

+2

+1: Tal vez tenga que "pedir prestada" esa línea para mi próxima revisión de código ;-) – RBerteig

+1

¿Hay alguna otra definición de "obras"? – spiderman

+0

¡Qué gran cita, gracias! – Charlie

0

Una vez que se ejecuta al final de la matriz, está sobreescribiendo la memoria que el software no está esperando y corrompiendo el montón. Su software puede continuar ejecutándose, pero será muy inestable.

0

Depende de cómo se empaqueta la memoria de la pila. Además, con mucho gusto sobrescribirá esos valores e incluso los leerá, pero lo más probable es que esté corrompiendo la pila.

5

Lo que está viendo es comportamiento indefinido, provocado al acceder a la matriz con un índice no válido. Comportamiento no definido significa que cualquier cosa podría suceder, incluido el programa que parece funcionar correctamente.

2

Las matrices en C no se verifican en el tiempo de ejecución. En otras palabras, puede "definir" una matriz de tamaño N y acceder alegremente al final del límite de la matriz. Si sale del extremo de la matriz, destruirá la memoria en algún lugar de la pila (o del montón).

Una vez que basura la memoria en alguna parte, su programa es probable que se bloquee. Estos bloqueos pueden ser difíciles de rastrear, ya que pueden bloquearse lejos de donde realmente se pasó el final de la matriz.

Normalmente cuando se declara matrices en C, lo mejor es utilizar algún tipo de constante o #define para marcar el tamaño de la matriz:

#define MAX_ELEMENTS 10 
int array[MAX_ELEMENTS]; 
int cnt; 
for(cnt = 0; cnt < MAX_ELEMENTS; cnt+=1) { 
    array[cnt] = cnt; 
} 

Si se pasa de max_elements en la asignación de matrices, es posible que sobrescribe el valor de cnt.Puede sobrescribir alguna otra variable. Todo depende del compilador y la estructura del código. También tenga en cuenta el uso del signo < en el ciclo for. Las matrices en C están basadas en 0, por lo que debe verificar utilizando menos que y no menos que o igual.

4

Me gustaría señalar que todo esto no está definido. Su ejemplo "funciona" en este ejemplo específico porque ambas variables se encuentran en la pila. Esa es la dirección de cnt justo debajo del final de la matriz. Cuando cnt alcanza cnt == 5 el conjunto de sentencias [cnt] = cnt; no escribe en la memoria dedicada a la matriz, sino justo después, donde se encuentra la dirección de cnt. Es solo suerte que no altera tu contador. Cuando cnt> 5 no hay memoria en la papelera y solo escribirá en el "stack void" (no conoce la palabra correcta).

otro ejemplo para ilustrar este:

int main(int ac,char **av) 
{ 
    int a[5]; 
    int cnt; 
    int cnt2=3; 

    for(cnt=0;cnt<7;cnt++) { 
     a[cnt]=cnt; 
     printf("%d %d %d\n", a[cnt], cnt, cnt2); 
    } 
} 

salida:

0 0 3 
1 1 3 
2 2 3 
3 3 3 
4 4 3 
5 5 5 
6 6 5 

Las dos últimas escrituras del bucle sobrescribe los datos de la pila después de a [] y pueden producir errores muy confuso. En este caso, el cnt2 está destrozado.

+0

Bonita ilustración. Lamentablemente, no puedo marcar dos mejores respuestas aquí. : \ – spiderman

1

Los límites de matriz en C son no necesariamente comprobados en tiempo de ejecución. El estándar deja a los implementadores en libertad de hacerlo si lo desean, o no, eso es parte de lo que es undefined. En una implementación con punteros gordos, la muestra podría de hecho causar algún tipo de error.

Cuestiones relacionadas