Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiler warning on seemingly compatible function pointer assignment (const vs no-const)

Tags:

c

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 };
like image 495
WTFBBQHAX Avatar asked Aug 27 '13 06:08

WTFBBQHAX


3 Answers

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

like image 109
alk Avatar answered Nov 09 '22 22:11

alk


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.

like image 38
Uchia Itachi Avatar answered Nov 10 '22 00:11

Uchia Itachi


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.

like image 32
TheCodeArtist Avatar answered Nov 09 '22 22:11

TheCodeArtist