Confusion about pointers and multidimensional arrays
c, multidimensional-array, pointers
Solution
First, some standard language:
6.3.2.1 Lvalues, arrays, and function designators ... 3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
Given the declaration
int myarray[3][3];
the type of `myarray` is "3-element array of 3-element array of `int`". Going by the rule above, when you write
MyFunction(myarray, 3, 3);
the expression `myarray` has its type implicitly converted ("decay") from "3-element array of 3-element array of `int`" to "pointer to 3-element array of `int`", or `int (*)[3]`.
Thus, your function prototype would need to be
int MyFunction(int (*array)[3], int row, int col)
Note that `int **array` is not the same as `int (*array)[3]`; the pointer arithmetic will be different, so your subscripts won't wind up pointing to the right places. Remember that array indexing is defined in terms of pointer arithmetic: `a[i]` == `*(a+i)`, `a[i][j] == *(*(a + i) + j)`. `a+i` will yield a different value depending on whether `a` is an `int **` or an `int (*)[N]`.
This particular example assumes you're always passing an Nx3-element array of `int`; not terribly flexible if you want to deal with any NxM-sized array. One way to get around this would be to explicitly pass the address of the first element in the array, so you're just passing a simple pointer, and then compute the proper offset manually:
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);
Since we pass a simple pointer to `int`, we can't use a double subscript in `MyFunc`; the result of `arr[i]` is an integer, not a pointer, so we have to compute the full offset into the array in the one subscript operation. Note that this trick will only work for truly multidimensional arrays.
Now, a `**` can indicate values that are organized in a 2-D structure, but one that was built a different way. For example:
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);
...
}
Going by the rule above, when the expressions `d0`, `d1`, and `d2` appear in the initializer for `a`, their types are all converted from "3-element array of `int`" to "pointer to `int`". Similarly, when the expression `a` appears in the call to `AnotherFunc`, its type is converted from "3-element array of pointer to `int`" to "pointer to pointer to `int`".
Note that in `AnotherFunc` we subscript both dimensions instead of computing the offset like we did in `MyFunc`. That's because `a` is an array of pointer values. The expression `arr[i]` gets us the i'th pointer value offset from the location `arr`; we then find the j'th integer value offset from that pointer value.
The following table might help - it shows the types of various array expressions and what they decay to based on their declarations (`T (*)[N]` is a pointer type, not an array type, so it doesn't decay):
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
The pattern for higher-dimensional arrays should be clear.
Problem
If the following is possible: ``` MyFunction(int *array, int size) { for(int i=0 ; i<size ; i++) { printf(“%d”, array[i]); } } main() { int array[6] = {0, 1, 2, 3, 4, 5}; MyFunction(array, 6); } ``` Why the following is not? ``` MyFunction(int **array, int row, int col) { for(int i=0 ; i<row ; i++) { for(int j=0 ; j<col ; j++) { printf(“%d”, array[i][j]); } } } main() { int array[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; MyFunction(array, 3, 3); } ```