I have encountered this while writing a program with matrices, I used int** m
to declare my matrix - because I needed dynamic allocation and in the function i used int a[][]
. I don't remember having any problem with that. But when I used a simple m[6][6]
matrix and f(int**m, int** m2, rest params)
I had trouble.
It compiled and when I was running the program (code blocks with GCC) it just crashed. I tried debugging by adding printf()
s and it was crashing at an if()
block where it made no sense to crash. Modified the first function parameter from int a[][]
to int* a[6]
and it moved on, modified the second param later and my program worked on first try. By a more careful debug what I was saving in int m[i][j]
and checking in the if was junk value, not what I was putting in, I was just putting 1
or 0
to mark something.
After all this years, unless I get compiler error by GCC when I do stuff like this, I just write the first way that comes to mind.
What is the logic behind using int**
and int [][]
to declare variable/get function parameters, in all 4 combinations? Most predefined functions I worked with use int**
in the function header.
I know int [][]
is not equivalent to int**
, it is int* []
correctly, but what are the things that i'm missing? int[][]
is an multi dimensional array means array of arrays, all 3 ways of writing it seem the same. And for int[][]
it almost always asks to only let the first parameter void, like for int array[][][][]
I need to put int array a[][n1][n2][n3]
in the function parameter, right? It needs to know the dimension for multi-dimensional arrays except for the first one, because int*
and int[]
can be used without problems when declaring function arguments?
What are the exact differences betwenn
int **a
andint a[][]
as function parameters in C and C++?
int *a
. This is a pointer to an int.
int **a
. This is a pointer to pointer to an int.
int a[]
This would be an array of unspecified number of ints in all other contexts, but as a function parameter declarator, it is adjusted to be a pointer to int i.e. in that case it is same as if you had written int *a
.
int a[][]
This would be an array of unspecified number of arrays of unspecified number of ints, but such type is ill-formed because the array element cannot be an array of unspecified size.
int *a[]
This would be an array of unspecified number of pointers to int in all other contexts, but as a function parameter declarator, it is adjusted to be a pointer to pointer to int i.e. in that case it is same as if you had written int **a
.
int (*a)[N]
This is a pointer to an array of N ints.
int a[][N]
This would be an array of unspecified number of arrays of N ints in all other contexts, but as a function parameter declarator, it is adjusted to be a pointer to an array of N int i.e. in that case it is same as if you had written int (*a)[N]
.
Some examples:
void fun_1D(int*); // argument is pointer to int
void fun_1D(int[]); // same as above
void fun_1D(int[10]); // same as above; note that 10 is ignored
int arr_1D[20]; // array of int
fun_1D(arr_1D); // implicit conversion
fun_1D(&arr_1D[0]); // same as above
void fun_2D(int (*)[20]); // note that 20 is not ignored
void fun_2D(int[][20]); // same as above
void fun_2D(int[10][20]); // same as above; note that 10 is ignored
int arr_2D[20][20]; // array of array of int
fun_2D(arr_2D); // implicit conversion
fun_2D(&arr_2D[0]); // same as above
fun_1D(arr_2D[i]); // implicit conversion
fun_1D(&arr_2D[i][0]); // same as above
void fun_ptrs(int**); // argument is pointer to pointer to int
void fun_ptrs(int*[]); // same as above
void fun_ptrs(int*[10]); // same as above; note that 10 is ignored
int *arr_ptr[20]; // array of pointers
fun_ptrs(arr_ptr); // implicit conversion
fun_ptrs(&arr_ptr[0]); // same as above
fun_1D(arr_ptr[i]); // no conversion needed
// broken examples
fun_2D(arr_ptr); // int*[20] is not int(*)[20]
fun_ptrs(arr_2D); // int[20][20] is not int**
Notice how a function parameter declared as an array is adjusted as the same pointer type to which an array will decay to upon lvalue to rvalue conversion.
Some simple rules of thumb to remember:
If I declare int a[6][6] in main and call a function that expects int** a, will it workd?
No, because int[6][6]
is not an int**
and neither does it decay to one. int[6][6]
decays to int(*)[6]
as I explained above. int(*)[6]
and int**
are not convertible to one another. One is pointer to an array, the other is pointer to a pointer.
And the other way around
No, because int[6][6]
argument is adjusted to int(*)[6]
. See previous paragraph for reason why these are incompatible.
seems
int a[][]
is not accepted
Correct. As I explained in the fourth paragraph from the top (not counting the quote).
If I have functions f1(int *a) and f2(int a[]) and f2(int a[6]) what would sizeof (a) return in those cases ?
As I explained above, all of those declare a parameter of type int*
. sizeof a
would be same as sizeof(int*)
because that is the type.
int **a
This is pointer to pointer to int.
int a[][]
This is array of array of int but this is not valid because the dimension of the second array must be known at declaration time, i.e. the second array must be complete, as it cannot be completed afterwards, like that
int a[][DIM]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With