SomeWittyUsername
SomeWittyUsername

Reputation: 18368

Function pointers assignment

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

Answers (2)

Pascal Cuoq
Pascal Cuoq

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

NPE
NPE

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

Related Questions