Reputation: 1158
In parseFunc() if I call loadFunc() by passing &tIpArray, it compiles fine when using C as the compile(in onlinegdb.com) but complains as below on a later version of C compiler(gcc-bin/4.9.4/gcc) at work.
Error at work is similar to what I see when I compile when using language as C++ in onlinegdb. Can someone tell me why the 4.9.4 gcc C compiler doesn't like the & and what is the right way to handle this?
/******************************************************************************
Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, PHP, Ruby,
C#, VB, Perl, Swift, Prolog, Javascript, Pascal, HTML, CSS, JS
Code, Compile, Run and Debug online from anywhere in world.
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
typedef struct _MyStruct
{
char string[72];
}MyStruct;
int loadFunc(MyStruct** ipData, int counter)
{
MyStruct **currentVal = ipData;
MyStruct *ipPtr = NULL;
printf("%p\n", currentVal);
for(int i=0; i<counter; i++)
{
ipPtr = currentVal[i];
printf("Line-%d - %s - %p\n", i+1, ipPtr->string, ipPtr);
}
}
int parseFunc()
{
MyStruct* tIPArray[3];
for(int i=0; i< 3; i++)
{
tIPArray[i] = 0;
tIPArray[i] = (MyStruct*) calloc(1, sizeof(MyStruct));
snprintf(tIPArray[i]->string, 72, "Test-String-%d", i+101);
}
for(int i=0; i<3; i++)
{
printf("Line-%d %p-%p- %s\n", i+1, &tIPArray[i], tIPArray[i], tIPArray[i]->string);
}
// call the load/ print loadFunc
loadFunc(&tIPArray, 3);
}
int main()
{
printf("Hello World\n");
parseFunc();
return 0;
}
Below is the error I get at work
error: passing argument 1 of 'loadFunc' from incompatible pointer type [-Werror] loadFunc(&tIPArray, 3); note: expected 'struct MyStruct **' but argument is of type 'struct MyStruct * (*)[(sizetype)((int)((short unsigned int)getMaxAddressObjects() / 4u))]' int loadFunc(MyStruct **ipData, int counter)
Below error when building this in onlinegdb.com as C++ file
main.cpp: In function ‘int parseFunc()’: main.cpp:49:38: error: cannot convert ‘MyStruct * (*)[3] {aka MyStruct * (*)[3]}’ to ‘MyStruct ** {aka MyStruct **}’ for argument ‘1’ to ‘int loadFunc(MyStruct **, int)’ loadFunc(&tIPArray, 3);
Upvotes: 0
Views: 196
Reputation: 19113
Perhaps it can be clearer if we use typedef MyStruct* StrPtr;
. Then your example becomes:
void foo(StrPtr* bar);
StrPtr array[4];
First, let look at this call:
foo(array);
Array is of type StrPtr[4]
, not StrPtr*
. Ideally this would call foo(StrPtr bar[4])
but there's no such function. The next best match is that arrays can decay to pointers to their elements = StrPtr*
and luckily there's foo(StrPtr* bar)
function so the call is valid.
Now, what is type of this expression?
&array;
Well, again array is of type StrPtr[4]
so this must be a pointer to that type = StrPtr(*)[4]
. Same "weird" syntax as for function pointers.
At last, take this call:
foo(&array);
We now know that this would like to call foo(StrPtr(*bar)[4])
and again there's no such function. So what can compiler do? &array
is not an array, it's a pointer and pointers cannot decay to anything. Hmm, what now? Well, in C any pointer can be passed to another no matter the type. Dereferencing such pointer is another thing. So, this call is valid and calls foo(StrPtr* bar)
as there's no other candidate. Success? No, any decent compiler should warn against this, even better turning those warnings into errors using -Wincompatible-pointer-types
or even forbid all warnings with -Werror
as you did.
So, the take away is that correct call is foo(array);
.
Upvotes: 2
Reputation: 180201
This declaration ...
MyStruct* tIPArray[3];
declares tIPArray
as an array of 3 MyStruct *
. Therefore, &tIPArray
is a pointer to such an array, its type is MyStruct *(*)[3]
, just as the error message says. This is not the same type as MyStruct **
, which is the expected type of the function argument.
You can instead pass an explicit pointer to the first element ...
loadFunc(&tIPArray[0], 3);
... but it would be more idiomatic to just omit the &
, since ordinary conversion of array to pointer ("decay" of the array) produces a pointer of the correct type and value:
loadFunc(tIPArray, 3);
Upvotes: 2