#include<stdio.h>
void foo(int **arr) {
arr[1][1]++;
}
main() {
int arr[20][20];
printf("%d\n",arr[1][1]);
foo((int**)arr);
printf("%d\n",arr[1][1]);
}
6 Answers
Suppose you declare: int arr[ 10 ][ 20 ] ;
What type is arr?
You may think that it'sint **, but that's incorrect.Its actually of type
int (*)[20]when it decays (like when you pass it to a function);
Array decaying applies only once.
Now consider the following,
#include<stdio.h>
#include<stdlib.h>
void foo(int arr[][20]) {
arr[1][1]++;
}
main() {
int (*arr)[20];
arr = malloc(sizeof(int (*)[]) * 2); //2 rows & malloc will do implicit cast.
printf("%d\n",arr[1][1]);
foo(arr);
printf("%d\n",arr[1][1]);
}
Output :
$ gcc fdsf.c && ./a.out
0
1
arr and arr+1 are pointing to array of 20 integers.
arr + 0 --> int int int ... int (20 ints, contiguous)
[0][0] [0][1]
arr + 1 --> int int int ... int (20 ints, contiguous)
[1][0] [1][1]
3 Comments
int[10][12], although it decays to int(*)[10]. Look at sizeof(arr) to see this.int(*)[12]?sizeof *arr to see this ;-)Here's what an int[2][2] looks like in memory:
int[2] int[2]
That is, an array immediately followed by another array.
Here's what an int[2] looks like in memory:
int int
That is, an int immediately followed by another int.
So, here's also what an int[2][2] looks like in memory:
int int int int
^ ^
| |___ this is arr[1][1]
|
|____ this is p[1], assuming sizeof(int*) == sizeof(int)
If you cast arr to an int**, I'm going to call the result p. Then it points to the same memory. When you do p[1][1] you don't get arr[1][1]. What the program does instead is, it reads the value at p[1], adjusts that up by the size of an int, and dereferences it. If that second int contained, say, the value "21" then you have just tried to dereference the pointer "25" (if int is 4 bytes). That ain't right.
Arrays are not the same as pointers, and 2-D arrays are certainly not the same thing as pointers-to-pointers.
Comments
If you change it like this, you get the expected result:
#include<stdio.h>
void foo(int arr[][20]) {
arr[1][1]++;
}
int
main() {
int arr[20][20];
arr[1][1] = 1;
printf("%d\n",arr[1][1]);
foo(arr);
printf("%d\n",arr[1][1]);
}
1 Comment
foo needs to know the array size (well, at least the second array dimension, first isn't needed), otherwise it can't do the necessary pointer arithmetic for the [1][1].
6 Comments
arr were a true int** ragged array then the compiler would not need to know the size of either dimension, nor would it crash when accessing the array items. If the OP had written void foo(int arr[][]) and gotten a compile error about a missing dimension then your answer would be correct. As is it is only the tip of the iceberg. @Steve Jessop explains better why the program crashes, IMO.