I have the function with following signature:
void box_sort(int**, int, int)
and variable of following type:
int boxes[MAX_BOXES][MAX_DIMENSIONALITY+1]
When I am calling the function
box_sort(boxes, a, b)
GCC gives me two warnings:
103.c:79: warning: passing argument 1 of ‘box_sort’ from incompatible pointer type (string where i am calling the function)
103.c:42: note: expected ‘int **’ but argument is of type ‘int (*)[11] (string where the function is defined)
The question is why? Whether int x[][] and int** x (and actually int* x[]) are not the same types in C?
When an array expression appears in most contexts, its type is implicitly converted from "N-element array of T" to "pointer to T", and its value is set to the address of the first element in the array. The exceptions to this rule are when the array expression is an operand of the
sizeof
or address-of (&
) operators, or if the array expression is a string literal being used to initialize another array in a declaration.What this means in the context of your code is that in your call to
box_sort
, the type of the expressionboxes
is implicitly converted fromM-element array of N-element array of int
topointer to N-element array of int
, orint (*)[MAX_DIMENSIONALITY+1]
, so your function should be expecting parameter types like:Since
int *a
andint a[]
are synonymous in a function parameter declaration, it follows thatint (*a)[N]
is synonymous withint a[][N]
, so you could write the above asalthough I personally prefer the pointer notation, as it more accurately reflects what's going on. Note that in your function, you would subscript
arr
as normal:since the expression
arr[x]
is equivalent to*(arr + x)
, the pointer is implicitly dereferenced.If you want box_sort to work on arbitrarily-sized arrays (i.e., arrays where the second dimension isn't necessarily MAX_DIMENSIONALITY+1), then one approach is to do the following:
Basically, you're treating
boxes
as a 1-d array of int and calculating the offsets manually.You never constructed an array of pointers as the signature requires.
There are two ways to do 2D arrays in C. In one case, you just have a lot of something and the compiler is told what the dimensions are. It calculates the beginning of the row by multiplying the row index by the number of columns and then it adds the column index to find the element within that row.
The other way is with a vector of pointers, where the compiler just dereferences the vector to find the beginning of the row, but the compiler won't make these for you automatically, you have to do it yourself.
Your actual object is one of the first kind, but your function prototype is asking for the second kind.
So you should either change the prototype to match the object or construct a vector of row pointers to pass to the function.
There is no such type in C as
int[][]
, only the first part of a multidimensional array can be unspecified. Soint[][5]
is okay.In addition to the other answers posted here, if you can use C99, you can use variable arrays to accomplish what you want:
This will work on most platforms except Microsoft's Visual C++.
I know there was a question almost exactly like this a couple days ago... can't find it now though.
The answer is,
int[size][]
(see note at the bottom) andint**
are definitely not the same type. You can useint[]
andint*
interchangeably in many cases, in particular in cases like this because the array decays to a pointer to the first element when you pass it into a function. But for a two-dimensional array, these are very different methods of storing.Here's what they'd look like in memory for a 2x2 array:
You could construct the second one like this:
Note: As others have noted,
int[][]
isn't a real type; only one of the sizes can be unspecified. But the core of the question here is whether a two-dimensional array and a double pointer are the same thing.