DQQpy DQQpy - 3 months ago 18
C Question

Incompatible pointer type array to pointer

I have a problem with pointer types. GCC compiler throws a warning like this:

416:31: warning: passing argument 1 of 'locateInHWNDArray' from
incompatible pointer type [-Wincompatible-pointer-types]
locateInHWNDArray(hWndLWTxt, (HWND)lParam, &x, &y);
^
foodplaner.c:76:6: note: expected 'struct HWND__ ***'
but argument is of type 'struct HWND__ * (*)[4]'
void locateInHWNDArray(HWND **array, HWND el, int *x, int *y);
^


The function signature looks like this:

void locateInHWNDArray(HWND **array, HWND el, int *x, int *y)


and the call is the following

locateInHWNDArray(hWndTWTxt, (HWND)lParam, &x, &y);


with hWndTwTxt declared as

HWND hWndTWTxt[7][4];


I assume this has to do something with having it declared with a certain size, but I have no idea what the compiler exactly wants.

Answer

The problem is that a two-dimensional array and a pointer to a pointer are not the same thing.

foodplaner.c:76:6: note: expected 'struct HWND__ ***' but argument is of type 'struct HWND__ * (*)[4]'

The first part of this error message (before the "but") simply means that HWND is equivalent to a HWND__ * (where HWND__ is a type defined in a header file included in your project).

The second part of the error message (after the "but") is telling you that hWndTwTxt is being passed as a pointer to an array of 4 HWND__ *. This is consistent - a 2D array of dimension [7][4] is passed as a pointer to an array of 4 elements.

In combination, the error message is telling you that a 2D array cannot be converted into a pointer to a pointer.

Assuming your function needs to be passed something that resembles a 2D array then you either need specify your function as

void locateInHWNDArray(HWND array[7][4], HWND el, int *x, int *y)

or as

void locateInHWNDArray(HWND (*array)[4], HWND el, int *x, int *y)

Either of these rely on the second (right-most) dimension (i.e. 4) being known at compile time. Either way, the function must use valid array indices (i.e. when doing something with array[i][j], i must be between 0 and 7 and j must be between 0 and 4).

If you really want to pass a HWND ** (i.e. not changing the function argument types) then you will need to do something like this

HWND **temp;
int i, j;
temp = malloc(7*sizeof(*temp));
for (i = 0; i < 7; ++i)
{
    temp[i] = malloc(4*sizeof(*temp[i]));
    for (j = 0; j < 4; ++j)
        temp[i][j] = hWndTWText[i][j];
}

locateInHWNDArray(temp, (HWND)lParam, &x, &y);

/* copy from temp back to `hWndTWText` if the function modifies elements */

for (int i = 0; i < 7; ++i)
    free(temp[i]);
free(temp);

The function still needs to ensure indices are valid (which, if the array dimension are not fixed at compile time, means they must be passed, somehow, to the function - for example, as additional arguments).