extern的一个小问题

SeeSeaBee 2007-09-06 03:13:50
写了一段代码
test.c
#include<stdio.h>

int main()
{
extern char filename[]="file";
char filename[]="file";
printf("%s\n",filename);
return 0;
}
以上的代码编译时会error,表明filename重复定义了
但是如果把代码改称下面的:
test.c
#include<stdio.h>

extern char filename[]="file";
char filename[]="file";
int main()
{
printf("%s\n",filename);
return 0;
}
程序可以正常编译和执行
不太明白原因,请大家解释一下
ps:我在debain下gcc编译
...全文
610 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhji09 2007-09-07
  • 打赏
  • 举报
回复
学习。
scholar165 2007-09-06
  • 打赏
  • 举报
回复
roadtang的说法是正确的.
如果在一个.c文件中用extern声明并且提供了初始值,那么则视为对你声明(引用)的那个变量的重新定义.
也就是说你定义的这个变量与你原本想要引用的那个变量占用的是两个不同的空间.例如:
在1.c中定义了一个变量: int i = 0;
如果你想要在2.c中引用在1.c中定义的这个变量i,那么只需要在2.c中加上语句
extern int i;或者在头文件2.h中添加extern int i;然后在2.c中包含2.h这个头文件就可以了.

但是,如果你在2.c中这样写
extern int i = 10;
那么2.c中你使用的变量就是i = 10,而不是在1.c中定义的那个变量了.
roadtang 2007-09-06
  • 打赏
  • 举报
回复
不太清楚,你的gcc为什么不报错.

C 标准上说
If the declaration of an identifier for an object has file scope and an initializer, the
declaration is an external definition for the identifier.

如果 全局域中的声明如果同时提供了初始量, 视为(外部的)定义.
所以不管怎样, 按C标准

在全局域
extern char filename[] = "file"; /*视为定义*/
char filename[]="file"; /* 又一个定义 */
这是错误的.




SeeSeaBee 2007-09-06
  • 打赏
  • 举报
回复
gcc -ansi -Wall -o test test.c
没有任何警告
可能是编译器版本不一样
飞哥 2007-09-06
  • 打赏
  • 举报
回复
没有那么写的吧:(


char * s = "test.txt"

extern char * s;
roadtang 2007-09-06
  • 打赏
  • 举报
回复
我这里过不了.

你的编译的时候连 "Warning"也没有?
SeeSeaBee 2007-09-06
  • 打赏
  • 举报
回复
用 gcc -ansi 编译第二种情况还是可以正常通过的啊

Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --with-tune=i686 --enable-checking=release i486-linux-gnu
Thread model: posix
gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)

roadtang 2007-09-06
  • 打赏
  • 举报
回复
我这里两种都报错的. 你用 gcc -ansi 编译一下试试?

====
#include <stdio.h>
extern char filename[] = "file";
char filename[]="file";
int main()
{
printf("%s\n",filename);
return 0;
}
$ gcc 5746194.c
5746194.c:8: 警告:‘filename’已初始化,却又被声明为‘extern’
5746194.c:9: 错误:‘filename’重定义
5746194.c:8: 错误:‘filename’的上一个定义在此
$ gcc -v
使用内建 specs。
目标:i686-pc-linux-gnu
配置为:../configure --prefix=/usr --enable-shared --enable-languages=c,c++,objc --enable-threads=posix --enable-__cxa_atexit --disable-multilib --libdir=/usr/lib --libexecdir=/usr/lib --enable-clocale=gnu --disable-libstdcxx-pch --with-tune=generic
线程模型:posix
gcc 版本 4.2.1


Treazy 2007-09-06
  • 打赏
  • 举报
回复
to SeeSeaBee
具体怎么实现我不和你争论了,但至少凭“预编译”完全可以解决重复定义的问题!
SeeSeaBee 2007-09-06
  • 打赏
  • 举报
回复
To Treazy
你的意思我明白
我假设的前提是.h中只是声明所有公用的变量,而在.c中定义变量
在有些情况下,在.h中定义变量编译时会引起重复定义的问题的
Treazy 2007-09-06
  • 打赏
  • 举报
回复
是不是编译器设置错误类型取消了类似的这样的错误不报呢?呵呵!
lddLinan 2007-09-06
  • 打赏
  • 举报
回复
搞不明白为什么可以编译通过,我的gcc只有这样才能通过:
extern char filename[];
char filename[]="file";
放到哪里都可以
Treazy 2007-09-06
  • 打赏
  • 举报
回复
说错了,是该看防止重复定义和应用的技巧,呵呵!
Treazy 2007-09-06
  • 打赏
  • 举报
回复
我明白了你的意思了,不过你还是有问题的!
对于你
extern char filename[]="file";
char filename[]="file";
的代码,我们分析一下
extern char filename[]="file";//filename[]已经在其他地方定义过了,因此这里只是引用
//只需要extern char filename[];
char filename[]="file"; //我不明白你这句是要干吗,我就当理解成你要重新赋值
//那就直接filename[]="file";干吗还要重新定义呢
最后象你这样说的方法很不好,
一般我们在.h当中就已经做好1方定义,多方引用的程序编写技巧了,无须再在.c中再去引用,除非是模块静态变量。建议楼主好好在看看关于重复定义和引用的技巧。
SeeSeaBee 2007-09-06
  • 打赏
  • 举报
回复
to Trezay()
extern的概念我清楚,我只是想知道以上两种区别的原因
另外,在某些时候是需要像我第二种情况中所说的那种定义方法的
比如把所有需要用的公用变量可以在一个file.h的头文件中声明,然后在某一个具体的.c文件中去定义某个在file.h声明过的变量
由于.c文件已经包含了file.h
所以就会出现类似
extern char filename[]="file";
char filename[]="file";
的情况,这也不是没有意义的
ysuliu 2007-09-06
  • 打赏
  • 举报
回复
同意Treazy()
你这种用法就有问题啊,你如果自己定义filename还从别的地方引用干嘛?
Treazy 2007-09-06
  • 打赏
  • 举报
回复
一般 extern的用法(只针对变量)是如:
文件1.c中定义了
int A;
若在2.c中想用这个A
则需要
extern int A;
作为引用标志

而函数无须作这个声明!
Treazy 2007-09-06
  • 打赏
  • 举报
回复
首先我觉得你应该把extern的概念理清楚一下
你上面给的代码有些地方是不可取的
首先extern是引用的意思,既然是引用那一般只是把其他地方定义过的变量拿到这里用而已,一般放在文件头部
而之后你又去重新定义了该变量,这语法本来就有问题,不知道你在debian 下怎么编译过的!
ouyh12345 2007-09-06
  • 打赏
  • 举报
回复
作用域不一样。
第一段代码里,两个变量都是局部变量。
第二段代码,一个是全局变量,另一个是局部变量

69,369

社区成员

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

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