Reputation: 139
everyone.
I use Visual Studio 2013 (C++) and defined a 2d array in main function:
int _tmain(int argc, char **argv)
{
int g[3][3] = { { 1, 2, 3, }, { 4, 5, 6, }, { 7, 8, 9, }, };
...
return 0;
}
then, I defined a function in Define 1:
Define 1:
void print_array(int **arr, int kx, int ky)
{
for (int i = 0; i < kx; i++) {
for (int j = 0; j < ky; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
I want to call this function from main function:
int _tmain(int argc, char **argv)
{
int g[3][3] = { { 1, 2, 3, }, { 4, 5, 6, }, { 7, 8, 9, }, };
print_array(g, 3, 3);
return 0;
}
The visual studio tells me that:
Error 1 error C2664: 'void print_array(int **,int,int)' : cannot convert argument 1 from 'int [3][3]' to 'int **'
I also know another definition method:
Define 2
void print_array(int (*arr)[3], int kx, int ky)
{
for (int i = 0; i < kx; i++) {
for (int j = 0; j < ky; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
Now it works.
My question is: I remenbered before that they (Define 1 and Define 2) worked both in old compiler, named you can pass array name as int **
or int (*p) []
correctly to another function. However in Visual Studio C++ it is not. Is Visual Studio C++ much stricter than other compiler ? Or I did something wrong?
Thank you very much!
Upvotes: 0
Views: 775
Reputation: 123458
Except when it is the operand of the sizeof
or unary &
operators, or is a string literal used to initialize a character array in a declaration, an expression of type “N-element array of T
” will be converted (“decay”) to an expression of type “pointer to T
”, and the value of the expression will be the address of the first element of the array.
When you call print_array( g, 3, 3 );
, the expression g
has type “3-element array of T
”, where T
is “3-element of int
”. So g
will “decay” to type “pointer to T
”, or “pointer to 3-element of int
”, or int (*)[3]
. That’s why your second definition works.
Here’s a handy table to help remember some of these rules:
Type Decays to
———— —————————
T [N] T *
T [M][N] T (*)[N]
T [L][M][N] T (*)[M][N]
Upvotes: 1
Reputation: 213338
I remenbered before that they (Define 1 and Define 2) worked both in old compiler,
If the memory is correct, the old compiler was broken. The code was never valid C.
You can convert an array, int x[3]
, to a pointer, int *p
, freely. This has always worked, and there are many cases where it happens implicitly.
However, int (*x)[3]
is a pointer and int **y
is a pointer, but they point to completely different types of objects! You can't convert a int *
to a double *
either.
You can see that x
and y
have different structure if you draw them out:
+-------------+ +-----+
| int (*x)[3] | ----> | int |
+-------------+ | --- |
| int |
| --- |
| int |
+-----+
| ... |
+---------+ +-------+ +-----+
| int **y | ----> | int * | ----> | int |
+---------+ +-------+ +-----+
| ... | | ... |
They don't look the same at all, do they?
Upvotes: 6
Reputation: 37227
Array and pointer conversion can only be done on the 1st level, so int*
and int[]
fit well into each other, but not int**
and int[][]
.
Actually, int**
(can be converted to int(*)[]
) points to an array of pointers, each of which can point to different locations, but obviously the sub-arrays of a 2D array can't. That's the problem you're facing.
Upvotes: 1