tcc arm-linker与gcc ld处理外部变量时的区别

来源:互联网 发布:韩国听歌用什么软件 编辑:程序博客网 时间:2024/06/03 22:28
 几个函数源码如下:

[root@LinuxServer1 Test]# cat main.c
void printg1(void);
void printg2(void);


int main()
{
        printg1();
        printg2();

        return 0;
}
[root@LinuxServer1 Test]# cat g1.c
#include <stdio.h>

int g1=1;

void printg1(void)
{
        printf("In g1: %d/n", g1);
}


[root@LinuxServer1 Test]# cat g2.h
#include <stdio.h>
int g1;

[root@LinuxServer1 Test]# cat g2.c
#include "g2.h"

void printg2(void)
{
        int g2 = g1;
        printf("In g2: %d/n", g2);
}

执行编译命令gcc,正常通过:
[root@LinuxServer1 Test]# gcc -o global main.c g1.c g2.c

执行编译命令tcc,arm-linker出现Error:
$ tcc -o global main.c g1.c g2.c
Error: L6200E: Symbol g1 multiply defined (by g1.o and g2.o).
Error: L6200E: Symbol g1 multiply defined (by g2.o and g1.o).
Finished: 0 information, 0 warning and 2 error messages.

如果改变g2.h, 对已经初始化过的全局变量赋值如下:
[root@LinuxServer1 Test]# cat g2.h
#include <stdio.h>
int g1=2;

此时gcc编译调用ld才出现错误:
[root@LinuxServer1 Test]# gcc -o global main.c g1.c g2.c
/tmp/ccWysZOe.o(.data+0x0): multiple definition of `g1'
/tmp/ccsR2ozr.o(.data+0x0): first defined here
collect2: ld returned 1 exit status

由此可见,tcc比gcc有更严格的外部变量处理,如果此变量已经被定义且初始化,声明处如果没有加extern且没有赋值,gcc 将自动识别为extern变量,如果对其再次赋值才被认为是重定义。但是tcc则不然,如果没有明确指定为extern,那么tcc 将认为是重定义变量,无论有没有对此变量再次赋值。

说实话,我还没有去深究,究竟是gcc tcc处理导致的这个区别,还是ld, arm-linker的处理导致的这个区别,
暂时我需要了解到这些就可以解决手头问题了,以后有时间会深究一下。或者有了解编译的高人可以直接指点。
我会把您的结论添加进来。