Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why GCC compiles and links two files even if 'extern' is not used?

Tags:

c

extern

Following are the two separate codes written in two separate files Test1.c and Test2.c. I am not using extern keyword in any file.

//Test1.c
#include <stdio.h>

int a = 1;
int main()
{
    printf("test1 - a val = %d\n",a);
    fn();
    printf("After Return : %d",a);
}

//Test2.c
#include <stdio.h>

int a;
int fn()
{
    printf("test2 - a val = %d\n",a);
    a++;
}

I compiled this code using gcc:

gcc Test1.c Test2.c

It generates the following output:

test1 - a val = 1
test2 - a val = 1

I tried printing address of variable a in both codes. The address is also same.

Now I have following questions:

  1. Does gcc automatically compile and link even if extern is not used?? Here apparently gcc internally does that as I am compiling these two files together.
  2. Is this behaviour with/without extern keyword is compiler-dependent?
like image 259
sandeep.ganage Avatar asked Oct 18 '25 18:10

sandeep.ganage


1 Answers

This code is undefined behaviour with no diagnostic required. Test1.c and Test2.c both define an object a with external linkage, which violates C11 6.9/5:

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.

Note: "external definition" means a definition at file scope. (C11 6.9/4, 6.9/5). Some other comments/answers confuse "external definition" with "definition of object with external linkage", or "definition with extern keyword". static int x = 5; at file scope is an external definition.


As mentioned by Jonathan Leffler in comments, this particular result may be an intentional GCC extension. From C11 Annex J.5.11 "Common extensions" :

There may be more than one external definition for the identifier of an object, with or without the explicit use of the keyword extern; if the definitions disagree, or more than one is initialized, the behavior is undefined.

If gcc implements this extension then it would explain the behaviour you observed. Presumably "more than one is initialized" in that quote does not count the implicit initializer generated for a tentative definition.

like image 115
M.M Avatar answered Oct 20 '25 08:10

M.M



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!