关于外部变量的问题!求指教!!!

skyliuxu 2012-03-08 04:11:44
如果我在两个不同的源文件中,写同样的一条这样的语句,比如char buf[100]; 那么编译器会怎么处理呢,哪一个作为定义呢?我知道正常的应该是某一个加上extern作为声明,但是我想知道如果我不加编译器怎么看待这两个语句呢?求高人指教,在下愚钝!!!
...全文
141 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
skyliuxu 2012-03-12
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 oldm4n 的回复:]
代码如下:
file2.h

C/C++ code


int test2(void);



file1.c

C/C++ code


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "file2.h"

char dummy1[0];
char buf[100……
[/Quote]

impressive reasoning
skyliuxu 2012-03-12
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 dr8737010 的回复:]
根据<c缺陷与陷阱>一书描述:
如果一个程序对同一外部变量的定义不止一次,那么不同的系统会有不同的处理方式,大多数系统都会拒绝接受该程序.如果一个外部变量在多个源文件中定义却并没有指定初始值,那么某些系统会接受,而另外一些则不会接受.
因此,解决方法就是确保每个外部变量只被定义一次.
[/Quote]
这差不多是正解,果然归到了编译器不同处理方式的问题,路漫漫其修远兮!
skyliuxu 2012-03-12
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 fcmsuck 的回复:]
你初始化下试试,两边都初始化,
char buf[100] = {0};
[/Quote]
两边都初始化肯定是报错的,同一个外部变量只能有一个定义
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 skyliuxu 的回复:]

引用 3 楼 maoloverme1 的回复:
会有两个同名的实例,会报链接错误!

没有呀,并没有报错!!!
[/Quote]
你初始化下试试,两边都初始化,
char buf[100] = {0};
BadPattern 2012-03-09
  • 打赏
  • 举报
回复
根据<c缺陷与陷阱>一书描述:
如果一个程序对同一外部变量的定义不止一次,那么不同的系统会有不同的处理方式,大多数系统都会拒绝接受该程序.如果一个外部变量在多个源文件中定义却并没有指定初始值,那么某些系统会接受,而另外一些则不会接受.
因此,解决方法就是确保每个外部变量只被定义一次.
oldm4n 2012-03-08
  • 打赏
  • 举报
回复
10楼说的“见下帖”为12楼的贴
另外,12楼说的结论前提是以 gcc 做 linker,其余情况未考虑,也未验证。
oldm4n 2012-03-08
  • 打赏
  • 举报
回复
代码如下:
file2.h

int test2(void);


file1.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "file2.h"

char dummy1[0];
char buf[100];

int test1(void)
{
printf("dummy1: %p\n", dummy1);
printf("test1: buf (%p): %s\n", buf, buf);

return 0;
}

int main(void)
{
fgets(buf, 100, stdin);

test1();
test2();

fflush(stdin);
getchar();

return 0;
}


file2.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "file2.h"

char dummy2[0];
char buf[100];

int test2(void)
{
printf("dummy2: %p\n", dummy2);
printf("test2: buf (%p): %s\n", buf, buf);

return 0;
}


分析过程如下:
先分别编译出 file1.o 和 file2.o

gcc -g -Wall -c file1.c
gcc -g -Wall -c file2.c


在link出2个binary,link顺序一次是 file1.o 在前,另一次是 file2.o 在前

gcc -o f1-f2 file1.o file2.o
gcc -o f2-f1 file2.o file1.o


分别运行 f1-f2 和 f2-f1,结果如下(注意 dummy1、dummy2 及 buf 的地址)

root@debian:/tmp# ./f1-f2
123
dummy1: 0x80497a0
test1: buf (0x80497a0): 123

dummy2: 0x8049804
test2: buf (0x80497a0): 123


root@debian:/tmp# ./f2-f1
456
dummy1: 0x8049804
test1: buf (0x80497a0): 456

dummy2: 0x80497a0
test2: buf (0x80497a0): 456


由此可得出结论,在 gcc 4.4.5 下,先被link的obj里面的实例将屏蔽掉后被link的obj里的同等实例

root@debian:/tmp# gcc --version
gcc (Debian 4.4.5-8) 4.4.5

sgb_fish 2012-03-08
  • 打赏
  • 举报
回复
编译的时候只是检查你的语法,语义以及生成目标程序等等,两个文件中重名的变量不引起编译器报错时因为编译时文件独立编译的,而链接时链接程序要把你所有的目标程序链接在一起生成可执行程序,所以此时会发现重名的变量。用extern声明只是告诉编译器此文件中使用的这个变量不是本文件内的,连接时可以到外边寻找。static是告诉编译器我的这个变量不能在本文件之外引用,也就是static修饰的变量只在同一个文件内可见,对外部时不可见的。
oldm4n 2012-03-08
  • 打赏
  • 举报
回复
file1.c 及 file2.c 会被分别编译为 file1.o 和 file2.o,在每一份 obj 里面都会有一个 char buf[100]
当在两个c文件里声明buf时都加了static关键字,则不论是在vc还是在gcc下链接都不会报错,且运行后,两份buf互不相干
如果都不使用static关键字,则在vc下会报link错误,会说buf在某个obj中已定义(以先被link的为主,后被link的就会与先被link的冲突)
但是在gcc下link不报错(即使打开了 -Wall),运行的情形显示为lz所说的情况,“两份”buf 内容变成一样的了经过简单调试,“两份”buf的地址是同一个,以先被link的obj中的那份buf为准,代码及简单调试见下帖

[Quote=引用 9 楼 skyliuxu 的回复:]

引用 7 楼 hu7324829 的回复:
编译器不会保存 但是链接器时候会报错。

看 深入理解计算机系统--程序链接

我运行了程序,没有问题,链接没有报错,真的迷惘了
[/Quote]
skyliuxu 2012-03-08
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 hu7324829 的回复:]
编译器不会保存 但是链接器时候会报错。

看 深入理解计算机系统--程序链接
[/Quote]
我运行了程序,没有问题,链接没有报错,真的迷惘了
hu7324829 2012-03-08
  • 打赏
  • 举报
回复
http://www.cnblogs.com/kernel_hcy/archive/2010/01/27/1657411.html
hu7324829 2012-03-08
  • 打赏
  • 举报
回复
编译器不会保存 但是链接器时候会报错。

看 深入理解计算机系统--程序链接
skyliuxu 2012-03-08
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 baichi4141 的回复:]
编译器会告诉你它不知道该怎么处理。
[/Quote]
可我觉得编译器确实做出了某种解释,I just don't know how to get it tell me what it means.
skyliuxu 2012-03-08
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 maoloverme1 的回复:]
会有两个同名的实例,会报链接错误!
[/Quote]
没有呀,并没有报错!!!
skyliuxu 2012-03-08
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 wang0635 的回复:]
两个都是定义
每个文件中访问的都是各自文件中定义的那个
它们没有任何关系

如果一个加了extern
就变成一个了
[/Quote]
不是这样吧,我在file1里用一行fgets(buf, 100, stdin)之后,file2里的buf变得和file1里的一样,说明编译器是把他们看成一个的,不知道可不可以这样说?如果是这样,那哪一个是定义呢?
maoloverme1 2012-03-08
  • 打赏
  • 举报
回复
会有两个同名的实例,会报链接错误!
wang0635 2012-03-08
  • 打赏
  • 举报
回复
两个都是定义
每个文件中访问的都是各自文件中定义的那个
它们没有任何关系

如果一个加了extern
就变成一个了
baichi4141 2012-03-08
  • 打赏
  • 举报
回复
编译器会告诉你它不知道该怎么处理。

70,020

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧