Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function definition doesn't match its declaration in C but does in C++

When there is no visible declaration or definition of struct bar in the following code, it compiles successfully as C++ but not as C:

void foo(struct bar* p);

void foo(struct bar* p){}

int main(){}

Error message when compiled as C: error: conflicting types for 'foo'.

Can anyone explain this behaviour?

I have tried this with both clang++ 3.4 and g++ 4.8.2 with -Wall -Wextra -pedantic-errors flags and either -std=c99 or -std=c++03 for C and C++ respectively.

like image 227
Constructor Avatar asked May 24 '26 12:05

Constructor


1 Answers

Let's simplify the program by omitting the declaration and the useless main:

void foo(struct bar* p){}

The compiler sees struct bar, which has not been defined. The error message from GCC 4.8.2 explains what it does next:

a.c:1:17: warning: ‘struct bar’ declared inside parameter list [enabled by default]
 void foo(struct bar* p){}
                 ^
a.c:1:17: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default]

So now it assumes that struct bar is something that only exists within the definition of foo. The code compiles perfectly, though.

When you add the function prototype:

void foo(struct bar* p);

void foo(struct bar* p){}

the warning becomes:

a.c:1:17: warning: ‘struct bar’ declared inside parameter list [enabled by default]
 void foo(struct bar* p);
                 ^
a.c:1:17: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default]
a.c:3:17: warning: ‘struct bar’ declared inside parameter list [enabled by default]
 void foo(struct bar* p){}
                 ^
a.c:3:6: error: conflicting types for ‘foo’
 void foo(struct bar* p){}
      ^
a.c:1:6: note: previous declaration of ‘foo’ was here
 void foo(struct bar* p);
      ^

So like before, the compiler makes up a new, undefined type struct bar for the prototype, and another one for the function definition. So the prototype for foo and its definition refer to different types, both named struct bar. They don't match, hence the error.

The solution is to first forward-declare the struct:

struct bar;

void foo(struct bar* p);

void foo(struct bar* p){}

This compiles without warnings.

like image 119
Fred Foo Avatar answered May 26 '26 01:05

Fred Foo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!