Suppose the following code:
a.c:
#include <stdio.h>
int a;
int func();
int main(int argc, char **argv) {
a = 7;
int a2 = func();
printf("a is %d, a2 is %d\n", a, a2);
return 0;
}
and b.c:
int a;
int func()
{
a = 9;
return a;
}
When compiled with g++ a.c b.c -Wall -O0
it produces a linking error, as expected. However, when invoking gcc a.c b.c -Wall -O0
it produces no warning and no error!
The output is a is 9, a2 is 9
by the way.
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
Why does GCC allow this? I was surprised by this behaviour. If you initialize the variables at declaration, then linking will also fail with GCC.
When compiled with
g++ a.c b.c -Wall -O0
it produces a linking error, as expected. However, when invokinggcc a.c b.c -Wall -O0
it produces no warning and no error!
In your code a
has tentative definition (which becomes a full definition at the end of the current translation unit) which is valid in C. However, there's another such tentative definition which becomes a full definition in b.c
from another translation unit - both of which provide an external definition for a
in your program. In other words, a.c
and b.c
are fine on their own but isn't valid when they are combined either compiling together (either directly you do or by compiling them into separate modules and then making an executable by linking them). This is undefined behaviour:
C11, 6.9/5:
An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof or _Alignof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.161
However this is often supported as an extension by gcc. That's why when you invoke gcc
it compiles fine as C code. Strictly (standard-wise), this is invalid code in C.
When you invoke g++
to compile it as C++ code, it'd fails because C++ has no tentative definitions. It's not valid in C++. Hence, g++
errors out. See One Definition Rule in C++.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With