Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incompatible pointer type

Tags:

c

gcc

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?

like image 743
Boffin Avatar asked Mar 29 '10 17:03

Boffin


People also ask

What is incompatible pointer type in C?

Resolving Incompatible Pointer Types. In ISO C, a pointer to void can be assigned to a pointer of any other type. You do not need to cast the pointer explicitly. C++ allows void pointers to be assigned only to other void pointers.

Can array and pointer be used interchangeable?

A common misconception is that an array and a pointer are completely interchangeable. An array name is not a pointer. Although an array name can be treated as a pointer at times, and array notation can be used with pointers, they are distinct and cannot always be used in place of each other.


2 Answers

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) and int** are definitely not the same type. You can use int[] and int* 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:

int a[2][2]:

__a[0][0]__|__a[0][1]__|__a[1][0]__|__a[1][1]__
  (int)       (int)       (int)       (int)

int **a (e.g. dynamically allocated with nested mallocs)

__a__
(int**)
  |
  v
__a[0]__|__a[1]__
  (int*)  (int*)
    |        |
    |        |
    v        ------------------>
__a[0][0]__|__a[0][1]__        __a[1][0]__|__a[1][1]__
  (int)       (int)              (int)       (int)

You could construct the second one like this:

int **a = malloc(2 * sizeof(int*));
a[0] = malloc(2 * sizeof(int));
a[1] = malloc(2 * sizeof(int));

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.

like image 62
Cascabel Avatar answered Sep 27 '22 22:09

Cascabel


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.

like image 43
DigitalRoss Avatar answered Sep 27 '22 23:09

DigitalRoss