在正常情况下(没有额外的 gcc 标志),您应该可以将此代码编译为:
gcc file1.c file2.c
将会发生的事情是编译器会看到你有两个全局变量命名相同,并且都没有被初始化。然后它将您未初始化的全局变量放在代码的“公共”部分**。换句话说,它将只有一个“第一个”变量的副本。发生这种情况是因为默认gcc
为-fcommon
如果您要使用该-fno-common
标志进行编译,您现在会收到您正在考虑的错误:
/tmp/ccZNeN8c.o:(.bss+0x0): multiple definition of `first'
/tmp/cc09s2r7.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status
要解决此问题,您将添加extern
除一个变量之外的所有变量。
警告:
现在假设您有两个不同大小的全局未初始化数组:
// file1.c
int first[10];
// file2.c
int first[20];
好吧,猜猜看,编译它们不会gcc -Wall file1.c file2.c
产生警告或错误,并且变量是通用的,即使它的大小不同!!!
//objdump from file1.c:
0000000000000028 O *COM* 0000000000000020 first
//objdump from file2.c:
0000000000000050 O *COM* 0000000000000020 first
这是全局变量的危险之一。
**如果您查看objdump
*.o 文件中的一个(您必须编译gcc -c
才能生成它们),您会看到first
放在 common ( *COM*
) 部分:
mike@mike-VirtualBox:~/C$ objdump -t file2.o
a.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 file2.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 l d .data 0000000000000000 .data
0000000000000000 l d .bss 0000000000000000 .bss
0000000000000000 l d .rodata 0000000000000000 .rodata
0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack
0000000000000000 l d .eh_frame 0000000000000000 .eh_frame
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000004 O *COM* 0000000000000004 first
0000000000000000 g F .text 0000000000000039 main
0000000000000000 *UND* 0000000000000000 f
0000000000000000 *UND* 0000000000000000 printf