primer lugar, algunos standard idioma:
6.3.2.1 Lvalues, arrays y designadores de función
...
3 Excepto cuando es el operando del operador sizeof o la unario y operador, o es un literal de cadena usado para inicializar una matriz, una expresión que tiene tipo "matriz de tipo" se convierte en una expresión con tipo "puntero a tipo" que apunta al elemento inicial del objeto matriz y no es un lvalue Si el objeto de matriz tiene una clase de almacenamiento de registro, el comportamiento no está definido.
Dada la declaración
int myarray[3][3];
el tipo de myarray
es "matriz de 3 elementos de la matriz de 3 elementos de int
".A juzgar por la regla anterior, cuando se escribe
MyFunction(myarray, 3, 3);
la expresiónmyarray
tiene su tipo implícitamente convertido ("descomposición") de "matriz de 3 elementos de la matriz de 3 elementos de int
" a "puntero a 3 -elemento matriz de int
"o int (*)[3]
.
De este modo, el prototipo de la función tendría que ser
int MyFunction(int (*array)[3], int row, int col)
Tenga en cuenta que es int **array
no lo mismo que int (*array)[3]
; la aritmética del puntero será diferente, por lo que sus subíndices no terminarán apuntando a los lugares correctos. Recuerde que la indexación de matriz es definida en términos de aritmética de puntero: a[i]
== *(a+i)
, a[i][j] == *(*(a + i) + j)
. a+i
arrojará un valor diferente dependiendo de si a
es int **
o int (*)[N]
.
Este ejemplo particular asume que siempre está pasando una matriz de elementos Nx3 de int
; no es terriblemente flexible si quieres tratar con cualquier matriz de tamaño NxM. Una forma de evitar esto sería pasar explícitamente la dirección del primer elemento de la matriz, por lo que sólo estamos pasando un puntero simple, y luego calcular el desplazamiento adecuado de forma manual:
void MyFunction(int *arr, int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
printf("%d", a[i*col+j]);
}
int main(void)
{
int myarray[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
...
MyFunction(&myarray[0][0], 3, 3);
Como nos pase un puntero simple a int
, no podemos usar un doble subíndice en MyFunc
; el resultado de arr[i]
es un número entero, no un puntero, por lo que tenemos que calcular el desplazamiento completo en la matriz en la operación de un subíndice. Tenga en cuenta que este truco solo funcionará para matrices realmente multidimensionales.
Ahora, un **
puede indicar valores que están organizados en una estructura en 2-D, pero que se construyó de una manera diferente. Por ejemplo:
void AnotherFunc(int **arr, int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
printf("%d", arr[i][j]);
}
int main(void)
{
int d0[3] = {1, 2, 3};
int d1[3] = {4, 5, 6};
int d2[3] = {7, 8, 9};
int *a[3] = {d0, d1, d2};
AnotherFunc(a, 3, 3);
...
}
A juzgar por la regla anterior, cuando las expresiones d0
, d1
y d2
aparecen en el inicializador para a
, sus tipos son todos convertidos de "matriz de 3 elementos de int
" a "puntero a int
". De forma similar, cuando aparece la expresión a
en la llamada al AnotherFunc
, su tipo se convierte de "matriz de puntero de 3 elementos a int
" en "puntero a puntero a int
".
Tenga en cuenta que en AnotherFunc
subcribimos ambas dimensiones en lugar de calcular el desplazamiento como lo hicimos en MyFunc
. Eso es porque a
es una matriz de puntero valores. La expresión arr[i]
nos proporciona el 0thi puntero valor de desplazamiento desde la ubicación arr
; luego encontramos el j'th valor entero compensado de ese valor de puntero.
La siguiente tabla puede ayudar - que muestra los tipos de las diversas expresiones de la matriz y lo que se desintegran a la base de sus declaraciones (T (*)[N]
es un tipo de puntero, no un tipo de matriz, por lo que no se descompone):
Declaration Expression Type Implicitly Converted (Decays) to
----------- ---------- ---- --------------------------------
T a[N] a T [N] T *
&a T (*)[N]
*a T
a[i] T
T a[M][N] a T [M][N] T (*)[N]
&a T (*)[M][N]
*a T [N] T *
a[i] T [N] T *
&a[i] T (*)[N]
*a[i] T
a[i][j] T
T a[L][M][N] a T [L][M][N] T (*)[M][N]
&a T (*)[L][M][N]
*a T [M][N] T (*)[N]
a[i] T [M][N] T (*)[N]
&a[i] T (*)[M][N]
*a[i] T [N] T *
a[i][j] T [N] T *
&a[i][j] T (*)[N]
*a[i][j] T
a[i][j][k] T
El patrón para las matrices de mayor dimensión debe ser claro.
Encontré esto muy útil al iniciar la programación en C: http://cslibrary.stanford.edu/102/PointersAndMemory.pdf – helpermethod
eche un vistazo a la sección array vs puntero del c-faq (http: // c- faq.com/aryptr/index.html) – pmg