Pregunta

En C, sé que puedo asignar dinámicamente una matriz de dos dimensiones en el montón usando el siguiente código:

int** someNumbers = malloc(arrayRows*sizeof(int*));

for (i = 0; i < arrayRows; i++) {
    someNumbers[i] = malloc(arrayColumns*sizeof(int));
}

Es evidente que, en realidad esto crea una matriz unidimensional de punteros a un grupo de matrices unidimensionales de números enteros separados, y "El Sistema" se puede averiguar a qué me refiero cuando pido:

someNumbers[4][2];

Pero cuando declaro estáticamente una matriz 2D, como en la siguiente línea ...:

int someNumbers[ARRAY_ROWS][ARRAY_COLUMNS];

... no una estructura similar se crean en la pila, o se trata de otra forma por completo? (Es decir, que es una matriz de punteros 1D? Si no es así, ¿qué es y cómo se consiguen las referencias a descubierto?)

Además, cuando dije, "El Sistema", lo que es realmente responsable de averiguar que fuera? El kernel? ¿O es que el compilador de C a solucionar el problema al compilar?

¿Fue útil?

Solución

A estáticas bidimensionales miradas de matriz como una matriz de matrices - se acaba de poner a cabo de forma contigua en la memoria. Las matrices no son lo mismo que los punteros, pero debido a que a menudo se pueden utilizar más o menos intercambiable que puede ser confuso a veces. El compilador comprueba correctamente, sin embargo, que hace que todo se alinean muy bien. Usted tiene que tener cuidado con las matrices estáticas en 2D como usted menciona, ya que si se intenta pasar una a una función de tomar un parámetro int **, malas cosas van a suceder. Aquí está un ejemplo rápido:

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

En las miradas de memoria como esto:

0 1 2 3 4 5

exactamente lo mismo que:

int array2[6] = { 0, 1, 2, 3, 4, 5 };

Pero si se intenta pasar array1 a esta función:

void function1(int **a);

obtendrá una advertencia (y la aplicación dejará de acceder a la matriz correctamente):

warning: passing argument 1 of ‘function1’ from incompatible pointer type

Debido a que una matriz 2D no es el mismo que int **. La descomposición automática de una matriz en un puntero va solamente "un nivel profundo" por así decirlo. Es necesario para declarar la función como:

void function2(int a[][2]);

o

void function2(int a[3][2]);

Para hacer que todo sea feliz.

Este mismo concepto se extiende a n matrices dimensionales. Tomando ventaja de este tipo de negocios divertido en su aplicación general, sólo hace que sea más difícil de entender, sin embargo. Así que tenga cuidado ahí fuera.

Otros consejos

La respuesta se basa en la idea de que en realidad no C Tienes 2D matrices - posee conjuntos-de-matrices. Cuando se declara lo siguiente:

int someNumbers[4][2];

está solicitando someNumbers a ser una matriz de 4 elementos, donde cada elemento de matriz que es de tipo int [2] (que es en sí mismo una matriz de 2 ints).

La otra parte del rompecabezas es que las matrices siempre están dispuestas de forma contigua en la memoria. Si le preguntas a:

sometype_t array[4];

a continuación, que siempre se verá como la siguiente:

| sometype_t | sometype_t | sometype_t | sometype_t |

(4 sometype_t objetos distribuido junto a la otra, sin espacios en el medio). Así que en su conjunto someNumbers-of-matrices, que va a tener este aspecto:

| int [2]    | int [2]    | int [2]    | int [2]    |

Y cada elemento int [2] es en sí misma una matriz, que es similar al siguiente:

| int        | int        |

Así que en general, se obtiene lo siguiente:

| int | int  | int | int  | int | int  | int | int  |
unsigned char MultiArray[5][2]={{0,1},{2,3},{4,5},{6,7},{8,9}};

en la memoria es igual a:

unsigned char SingleArray[10]={0,1,2,3,4,5,6,7,8,9};

En respuesta a su también:. Ambos, aunque el compilador está haciendo la mayor parte del trabajo pesado

En el caso de las matrices asignadas estáticamente, "El Sistema" será el compilador. Se reservará la memoria como lo haría con cualquier variable pila.

En el caso de la matriz malloc'd, "El sistema" será el ejecutor de malloc (el núcleo por lo general). Todo el compilador asignará es el puntero de base.

El compilador siempre va a manejar el tipo como lo que se declaran excepto en el ejemplo Carl dio donde se puede averiguar el uso intercambiable. Por ello, si se pasa en un [] [] para una función que debe asumir que es un piso asignado estáticamente, donde ** se supone que es puntero a puntero.

Para acceder a una matriz 2D particular, considere el mapa de memoria para una declaración de matriz como se muestra en el código a continuación:

    0  1
a[0]0  1
a[1]2  3

Para acceder a cada elemento, su suficiente para sólo tiene que pasar qué matriz que le interesa como parámetros a la función. A continuación, utilice la columna de desplazamiento para el acceso a cada elemento por separado.

int a[2][2] ={{0,1},{2,3}};

void f1(int *ptr);

void f1(int *ptr)
{
    int a=0;
    int b=0;
    a=ptr[0];
    b=ptr[1];
    printf("%d\n",a);
    printf("%d\n",b);
}

int main()
{
   f1(a[0]);
   f1(a[1]);
    return 0;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top