First, Fun
should be defined with:
int Fun(int arr[][4])
rather than what you have, int Fun(int* arr[][4]);
.
Next, when Fun(arr)
is evaluated, arr
is automatically converted from an array of 3 arrays of 4 int
to a pointer to an array of 4 int
. Similarly, in the declaration of Fun
, int arr[][4]
is automatically adjusted to be a pointer to an array of 4 int
. So the argument type and the parameter type will match if you declare Fun
correctly.
You could also declare Fun
as:
int Fun(int (*arr)[4])
This is the same thing as above, due to the automatic adjustment that would be applied to the declaration above. Note that the asterisk here is grouped with the arr
by the parentheses. This makes it a pointer to an array of int
, rather than an array of pointers to int
.
Now, as to what will be printed, in main
:
printf("%p\n", arr);
In this statement, arr
will be automatically converted to a pointer to its first element, so it becomes a pointer to an array of 4 int
. Then the value of this pointer is printed. Note: When printing pointers, technically you should convert them to const void *
or void *
, as with printf("%p\n", (const void *) arr);
. However, omitting this likely does not cause a problem at the moment.
printf("%p\n", arr[0] + 1);
In this statement, arr[0]
is the first element of arr
. That first element is an array of 4 int
, and it is automatically converted to be a pointer to its first element. So arr[0]
becomes a pointer to the first int
. Then adding 1 advances the pointer to the next int
. The result is likely an address four bytes beyond arr
, depending on your C implementation. (It could be a different number of bytes, but four is the most common today.)
printf("%p\n", arr + 1);
In this statement, arr
is converted to a pointer to its first element, an array of 4 int
. Adding 1 advances to pointer to the next element, which is the next array of 4 int
. So this likely adds 16 bytes to the address.
Then, in Fun
:
printf("%p\n", arr); // address of first element
Here arr
is a pointer to an array of 4 int
. Its value is printed, yielding the same address as for the corresponding printf
in main
.
printf("%p\n", arr[0] + 1); // address increments by 4, pointing to next "inner array"
Here arr[0]
is the object pointed to by arr
, which is an array of 4 int
. Since it is an array, it is automatically converted to a pointer to its first element, which is an int
. So this points to the first int
. Then adding 1 advances to the next int
, and this again yields the same address as the corresponding printf
in main
.
printf("%p\n", arr + 1); // how does it know to increment address by 3 x 4 here? The complete array size
In this case, arr
is a pointer to an array of 4 int
, and adding 1 advances it to the next array of 4 int
, so the result is likely 16 bytes beyond the value of arr
, and this again yields the same address as the corresponding printf
in main
.
If you saw different values for the printf
statements in Fun
and main
, this was likely because of the incorrect declaration with int*
and because int *
is eight bytes in your C implementation, compared to four for int
. That error would have doubled some of the increments. You should not have seen any multiple of three in the increments.
Regarding the first dimension, Fun
does not need to know the first dimension because it never advances any pointers by units of the first dimension. It receives only a pointer to an array of 4 int
, and it does not need to know that there are 3 such arrays there.