views:

202

answers:

7

Why does this code

int (*g)(int);
int (*h)(char);
h = g;

In C, give me such warning when compiling:

'warning: assignment from incompatible pointer type'

In C++, can't be able to compile.

+2  A: 

One is declared to point to a function accepting an int, the other one - to a function accepting a char. Those are different signatures, so the pointers are incompatible.

sharptooth
+1  A: 

You've declared g to be a function taking one argument of type int and returning an int, and h to be a function taking one argument of type char and returning an int result. The two function signatures are not interchangeable and so you can't assign from a pointer to one to a pointer to the other.

moonshadow
A: 

You have declared g and h as functions. Actually, my compiler gives the error "lvalue required as left operand of assignment", and it seems strange that you could get this code to compile with just a warning?

EDIT: Originally, the code in the question declared g and h as functions. Now they have been changed to function pointers, which will indeed just give a warning.

Thomas Padron-McCarthy
+5  A: 

Prototypes don't match. g is a pointer to a function which takes an int and returns an int whereas h is a pointer to a function which takes a char and returns an int. They are two separate types and hence the warning (assigning apples to oranges).

dirkgently
Can someone explain the downvotes?
dirkgently
+3  A: 

The two functions pointers do not have the same signature, since the input parameters are different.

The function pointers both return an int, while g accepts an int as input, and h accepts a char as input parameters.

Although you can sometimes mix int and char, you are mixing function pointers, so the compiler correctly gives you a warning that you might be doing something wrong.

Example code:

#include <stdio.h>

int gf(int n)
{
    return printf("gf(%d)\n", n);
}

int hf(char c)
{
    return printf("hf('%c')\n", c);
}

int main()
{
    int (*g)(int) = gf; // pointer to gf
    int (*h)(char) = hf; // pointer to hf

    g = h; // warning: possibly incompatible functions

    g(65); // cast 65 to char and call h

    return 0;
}

Compiling:

$ gcc-4.exe -Wall a.c
a.c: In function 'main':
a.c:18: warning: assignment from incompatible pointer type

Running program:

$ ./a.exe
hf('A')

As you see, in C, it works nicely, but the compiler gives you a proper warning. If we try to compile this as C++ code, the compiler won't accept our pointer juggling:

$ g++-4.exe a.c
a.c: In function 'int main()':
a.c:18: error: invalid conversion from 'int (*)(char)' to 'int (*)(int)'
csl
A: 

Because you are assigning incompatible pointers. One function pointer takes a signed integer as an argument, the other char (signedness depends on your system). Even though both return the same, they are quite different.

Ignore the warnings, use the function pointers (while casting to make it actually compile) and you'll see what I mean :)

Tim Post
@dirkgently: noted and edited.
Tim Post
+1  A: 

Since the function signatures are different, this isn't legal C or legal C++. The question is why the compilers treat it differently. In neither standard is there much guidance on what to do with programs that violate the standard, except that certain violations require a diagnostic (and both of these cases do supply a diagnostic message). The standards are normally concerned with what a valid C or C++ program is, and what the implementation has to do when given one.

C is a considerably older language than C++, and a whole lot of C code was written on much less strict compilers than exist nowadays. C++ was stricter from the start, and so pre-standard C++ code tends to be valid standard C++ code that just doesn't use certain features.

For this reason, a C compiler is more likely to be lenient than a C++ compiler, assuming the compilers were written for practical use. After all, there's a lot of C code that blithely assumes things like this work, and some of that is very useful, but the same is not true of C++.

David Thornley