I ran into something funny that I think should be valid. Firstly:
Compiler/Version
$ gcc --version
gcc (Debian 4.7.2-5) 4.7.2
Compiler options and warning message.
$ gcc -c warn.c -o warn.o
warn.c:11:5: warning: initialization from incompatible pointer type [enabled by default]
warn.c:11:5: warning: (near initialization for ‘foo.exec’) [enabled by default]
I want to know why 'Foo()' is incompatible with 'exec'. (Added comments to hope-fully clarity)
typedef struct Thing
{
void (*exec)(char *abc);
} Thing;
// ME: I don't mess with this.. I make const, K?
void Foo(const char *abc)
{
(void) abc;
}
// GCC: LOL, nope! probably u messed up.
Thing foo = { Foo };
const char *
is not the same as char *
.
From the C-standard 6.7.5.3 (emphasis by me):
15 For two function types to be compatible, both shall specify compatible return types. Moreover, the parameter type lists, if both are present, shall agree in the number of parameters and in use of the ellipsis terminator; corresponding parameters shall have compatible types. [...]
From the C-standard 6.7.5.1 (emphasis by me):
2 For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.
Note: const
is a qualifier
Basically your function void Foo(const char *abc)
says that I will not modify
the variable which I point to.
But the functor int srtuct void (*exec)(char *abc)
says I might/mightnot modify
the variable.
This isn't acceptable.
It is just the compiler finding a mismatch in the function-signatures and issuing a warning and not an error since the function call will work just fine at runtime(same type/size/number of function params).
The apparent reason behind the warning is to help the programmer identify situations where the function-pointer is accidentally being assigned a function that co-incidentally accepts the same parameters but is distinctly different in its operation.
In the current example, the compiler can identify this based on the difference in intent implied by the
const
modifier applied to the function parameter.
Basically when you define the struct
as follows,
typedef struct Thing
{
void (*exec)(char *abc);
} Thing;
You are explicitly telling the compiler that the function pointer should point to only functions that match a specific signature (parameters and return-type).
This warning is easily fixed by updating the struct
definition as follows
typedef struct Thing
{
void (*exec)(const char *abc);
} Thing;
or can be completely side-stepped by not specifying the params at all
typedef struct Thing
{
void (*exec)();
} Thing;
in which case the compiler will NOT issue a warning as long as the return type constraint is satisfied.
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