Reputation: 18368
Following the question Function pointer in Visual Studio 2012 I've started to wonder about the legality of certain assignments to function pointers in C.
The code below compiles with a warning, like I would expect because the assigned function requires more parameters than the function pointer declaration describes (GCC 4.8):
#include <stdio.h>
int test(int x, int y)
{
printf("%d", x);
printf("%d", y);
return 0;
}
int main()
{
int (*test_ptr)(int);
test_ptr = test;
test_ptr(1);
return 0;
}
Same warning appears if changing the code so that assigned function requires less parameters (GCC 4.8). Again, this is expected.
However, the following code compiles without a single warning, although the assigned function needs 2 parameters instead of 0 (GCC 4.8):
#include <stdio.h>
int test(int x, int y)
{
printf("%d", x);
printf("%d", y);
return 0;
}
int main()
{
int (*test_ptr)();
test_ptr = test;
test_ptr();
return 0;
}
No castings are involved anywhere.
Can anyone explain this compiler behavior?
Upvotes: 4
Views: 3107
Reputation: 80355
Converting from function pointer to function pointer is legal. What is illegal is calling a function pointer with a type that is not compatible with the actual pointed function.
C99 6.3.2.3 par. 8:
A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined
If your compiler warned exactly for undefined behavior, it should warn at test_ptr();
. But compilers cannot be expected to warn for all undefined behaviors or to warn only for undefined behaviors.
This static analyzer (that others and I work on) does its best to warn on all undefined behaviors and only for undefined behaviors. A lot of compromises are involved, but in this particular case:
$ cat > fp.c
int test(int x, int y)
{
printf("%d", x);
printf("%d", y);
return 0;
}
int main()
{
int (*test_ptr)();
test_ptr = test;
test_ptr();
return 0;
}
$ frama-c -val fp.c
...
fp.c:13:[value] warning: Function type must match type at call site: assert(function type matches)
Line 13 is test_ptr();
.
Upvotes: 2
Reputation: 500953
The following:
int (*test_ptr)();
takes an unspecified number of parameters, not zero parameters.
For the latter, write
int (*test_ptr)(void);
P.S. Calling a two-argument function with zero arguments leads to undefined behaviour.
Upvotes: 9