// a.c
int a = 3;
 
// b.c
#include <stdio.h>
int a;
int main()
{
    printf("a=%d\n", a);
    return 0;
}
gcc a.c b.c -c
[hubingbing@pekphis193995 test_linkage2]$ readelf -s a.o

Symbol table '.symtab' contains 9 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS a.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     5: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    2 $d
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
     8: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    2 a
[hubingbing@pekphis193995 test_linkage2]$ readelf -s b.o

Symbol table '.symtab' contains 15 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS b.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
     6: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    5 $d
     7: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    1 $x
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
     9: 0000000000000014     0 NOTYPE  LOCAL  DEFAULT    8 $d
    10: 0000000000000000     0 SECTION LOCAL  DEFAULT    8 
    11: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
    12: 0000000000000004     4 OBJECT  GLOBAL DEFAULT  COM a
    13: 0000000000000000    44 FUNC    GLOBAL DEFAULT    1 main
    14: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND printf
[hubingbing@pekphis193995 test_linkage2]$ g++ a.c b.c -c
[hubingbing@pekphis193995 test_linkage2]$ readelf -s a.o

Symbol table '.symtab' contains 9 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS a.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     5: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    2 $d
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
     8: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    2 a
[hubingbing@pekphis193995 test_linkage2]$ readelf -s b.o

Symbol table '.symtab' contains 16 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS b.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
     5: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    4 $d
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
     7: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    5 $d
     8: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT    1 $x
     9: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
    10: 0000000000000014     0 NOTYPE  LOCAL  DEFAULT    8 $d
    11: 0000000000000000     0 SECTION LOCAL  DEFAULT    8 
    12: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
    13: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    4 a
    14: 0000000000000000    44 FUNC    GLOBAL DEFAULT    1 main
    15: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND printf
[hubingbing@pekphis193995 test_linkage2]$ 

特别注意,g++编译出来的b.o,a是在第4段,视作定义而非声明。而gcc编译出来的b.o,a在common段,视为声明,不分配空间。

所以上述代码gcc能编过并链接成功,而g++链接会报错。

// a.c
int x;
void func() {
    x = 20;
}
 
// b.c
#include "stdio.h"
 
short x = 10;
short y = 10;
extern void func();
 
int main()
{
    printf("before call func: x = %d, y = %d\n", x, y);
    func();
    printf("after call func: x = %d, y = %d\n", x, y);
    printf("sizeof(x)=%lu, sizeof(y)=%lu\n", sizeof(x), sizeof(y));
    return 0;
}
[hubingbing@pekphis193995 test_linkage]$ gcc a.c b.c
/usr/bin/ld: warning: alignment 2 of symbol `x' in /tmp/ccoKSrLO.o is smaller than 4 in /tmp/cc8Qpcod.o
/usr/bin/ld: warning: size of symbol `x' changed from 4 in /tmp/cc8Qpcod.o to 2 in /tmp/ccoKSrLO.o
[hubingbing@pekphis193995 test_linkage]$ ./a.out 
before call func: x = 10, y = 10
after call func: x = 20, y = 0
sizeof(x)=2, sizeof(y)=2