4

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?

2 Answers 2

9

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.

Sign up to request clarification or add additional context in comments.

1 Comment

@icepack C99 didn't deprecate functions with unspecified number of parameters.
2

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();.

4 Comments

If it's legal, why do the GCC warn in the first 2 code pieces?
@icepack because the compiler designers thought you might want to know that you are doing something unusual. In addition to not warning for every undefined behavior, it is allowed to warn for things that are not undefined behavior (or, in this case, for things that could result in undefined behavior that it knows it won't be able to warn about later if you use the pointer wrong).
@icepack Actually I am very surprised by the behavior described in the question you linked to (stackoverflow.com/questions/15653604/… ) but Visual Studio is known not to provide a C99 compiler and even if I dig up C90 and point out that it too allows that, that won't lead to it being fixed. The snippet in the question you linked is definitely C99-conformant.
it's not compliant but they have implemented some of the features. Besides, it's most likely being compiled as C++

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.