关于C中关键字extern的一点困惑

Rainman_Lu 2007-04-14 11:59:01
我在网上查了一下关于extern的基本解释是这样的:
================================================================
extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。
================================================================

我的理解是只要变量或者函数是在别的文件中定义的,那么要调用的话,一律要在调用前加上extern的申明。
但是我发现一些系统的头文件对函数的申明都是没有加extern的,比如在stdio.h中对printf的申明是这样的(VC++中):

_CRTIMP int __cdecl printf(const char *, ...);
(注:_CRTIMP 已在前面做了如下定义
#define _CRTIMP

假如我们在某个文件里include了stdio.h这个头文件,我的理解是对于printf的申明应该是这样的:
int printf(const char *, ...);
也就是说并没有用extern来标示printf的定义是在其它的模块中的。
但为什么我们却可以正常使用呢?

另外,我还在VC++下做了如下的尝试:
(1)在test.cpp中定义了函数void test(void);
(2)在main.cpp中尝试调用函数void test(void),
尝试一:
对函数的申明形式如下:
void test(void);
尝试二:
对函数的申明形式如下:
extern void test(void);
结果是这两次尝试都能成功调用函数,似乎extern的存在与否并不影响函数能否正常被调用,这让我很疑惑。

望高人能点拨一二,以解小弟的困惑,不胜感激!
...全文
516 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
fohonet 2007-04-16
  • 打赏
  • 举报
回复
在函数中使用全局变量,一般应作全局变量说明。 只有在函数内经过说明的全局变量才能使用。全局变量的说明符为extern。 但在一个函数之前定义的全局变量,在该函数内使用可不再加以说明。 例如:
int a,b; /*外部变量*/
void f1() /*函数f1*/
{
……
}
float x,y; /*外部变量*/
int fz() /*函数fz*/
{
……
}
main() /*主函数*/
{
……
}/*全局变量x,y作用域 全局变量a,b作用域*/
  从上例可以看出a、b、x、y 都是在函数外部定义的外部变量,都是全局变量。但x,y 定义在函数f1之后,而在f1内又无对x,y的说明,所以它们在f1内无效。 a,b定义在源程序最前面,因此在f1,f2及main内不加说明也可使用。
Rainman_Lu 2007-04-15
  • 打赏
  • 举报
回复
To all,
很感谢各位的回答,这些回答给了我许多的启发。

To dreamhmily2,
您的回答很有道理,但我还是不太理解关于内部链接,外部链接和extern的关系,
能否在您方便的时间里详细地再说明一下。谢谢!

另,我在网上找到了一段关于链接的文章,但毕竟是理论的东西,
我还是没办法很透彻的理解内部链接,外部链接和extern的关系。
这段文章里似乎说的是要用到外部函数的话都应该先用extern声明的。
不知道是不是在实际应用中对extern的使用有些特殊的处理。
(P.S.:段落有点长,我把一些重点用“『』”标了出来。)

Linkage

To understand the behavior of C and C++ programs, you need to know about linkage. In an executing program, an identifier is represented by storage in memory that holds a variable or a compiled function body. Linkage describes this storage as it is seen by the linker. There are two types of linkage: internal linkage and external linkage.

『Internal linkage means that storage is created to represent the identifier only for the file being compiled.』 Other files may use the same identifier name with internal linkage, or for a global variable, and no conflicts will be found by the linker – separate storage is created for each identifier. 『Internal linkage is specified by the keyword static in C and C++.』

『External linkage means that a single piece of storage is created to represent the identifier for all files being compiled.』 The storage is created once, and the linker must resolve all other references to that storage. 『Global variables and function names have external linkage. These are accessed from other files by declaring them with the keyword extern. Variables defined outside all functions (with the exception of const in C++) and function definitions default to external linkage.』 You can specifically force them to have internal linkage using the static keyword. You can explicitly state that an identifier has external linkage by defining it with the extern keyword. 『Defining a variable or function with extern is not necessary in C, but it is sometimes necessary for const in C++.』

Automatic (local) variables exist only temporarily, on the stack, while a function is being called. The linker doesn’t know about automatic variables, and so these have no linkage.

再次感谢各位!
msgsnd 2007-04-15
  • 打赏
  • 举报
回复
extern int a=0;
这可是定义啊,不是声明。
其实, int a=0;前面是有extern的,只不过省略了。
函数也一样,往往会省略。
这在一些比较老的代码中经常可以看到,主要是较低版本的语法,现在大家都不这样写了,方便吗。也不要看到感到奇怪。
lzp729 2007-04-15
  • 打赏
  • 举报
回复
上文中对这个的解释归纳而言,有两点
1. 在C语言中,为了强调一个函数或者全局变量具有的是文件作用域,应该使用static关键字,这样在同一工程中的其他编译模块中,也可以使用相同全局变量或函数名字,并且不会造成名字冲突
2. 在C++语言中,为了指定一个const量使用外部连接方式,必须要使用extern关键字。
关于第二点,我给出多一点的解释。要注意的是即使是想const量作为一个全局变量来声明(且不使用static关键字),那么这个const也无法被其他的编译模块所访问, 在定义这个const量的编译模块中,可以使用extern关键字使得这个const成为外部连接方式。给出两例:
// work ok
/* main.cpp */
#include <cstdlib>
#include <cstddef>
#include <iostream>
using namespace std;

extern int a;

int main()
{
cout << a;
system("Pause");
return EXIT_SUCCESS;
}
/* temp.cpp */
int a = 10;

// compile ok, link-time error
/* main.cpp */
#include <cstdlib>
#include <cstddef>
#include <iostream>
using namespace std;

extern const int a;

int main()
{
cout << a;
system("Pause");
return EXIT_SUCCESS;
}
/* temp.cpp */
const int a = 10;

// work ok
/* main.cpp */
#include <cstdlib>
#include <cstddef>
#include <iostream>
using namespace std;

extern const int a;

int main()
{
cout << a;
system("Pause");
return EXIT_SUCCESS;
}
/* temp.cpp */
extern const int a = 10;
dreamhmily2 2007-04-14
  • 打赏
  • 举报
回复
extern 表示将变量或函数声明为外部连接;
变量默认是内部链接,
函数默认是外部链接,因此用来外部连接的函数,声明时有无extern都可以连接通过..
而全局变量则不行..如是外部文件中定义的,一定需要声明成extern
guihudie 2007-04-14
  • 打赏
  • 举报
回复
因该不是特权的问题~~*.h文件里也有extern int _Cdecl errno;类似的定义~
loongee 2007-04-14
  • 打赏
  • 举报
回复
据我所知,*.h文件引用外部函数不需要extern,就可以起到引用其他文件中的函数的作用,可以使包含这个头文件的文件可以使用头文件中 声明 的函数。因为本来头文件就是用来连接文件与外部函数的。也许这就是编译器给*.h文件的特权吧。
fohonet 2007-04-14
  • 打赏
  • 举报
回复
mark!
guihudie 2007-04-14
  • 打赏
  • 举报
回复
关于extern 我的理解是:
extern 是个提前说明,如果你所定义的函数 void test(void);它的定义在调用之前的话那么有无extern 都是一样的,但是如果函数定义在调用只后的话就的加extern来声明,如我在file1.c中定义了void test(void); 函数,在file2.c中要使用test函数,这时候你如果在file3.c中写入 #include<file1.C>
#include<file2.C>
那么在file2.c中对函数test的声明有没有extern都无关
但是如果file3.c中是:
#include<file2.C>
#include<file1.C>
那么在file2.c中对函数test的声明必须有extern.
新人解答~有不对的地方还望指出~一起学习~


70,031

社区成员

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

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