声明外部变量

现代编译器一般采用按文件编译的方式,因此在编译时,各个文件中定义的全局变量是互相透明的,也就是说,在编译时,全局变量的可见域限制在文件内部。下面举一个简单的例子。创建一个工程,里面含有A.cpp和B.cpp两个简单的C 源文件:

//A.cpp
int i;
void main()
{
}
//B.cpp
int i;

这两个文件极为简单,在A.cpp中定义了一个全局变量i,在B中也定义了一个全局变量i。对A和B分别编译,都可以正常通过编译,但是进行链接的时候,却出现了错误,错误提示如下:

linking...
B.obj:errorLNK2005: "int i" (?i@@ 3HA ) already defined in A.obj
Debug/A.exe:fatal error LNK1169: one or more multiply defined symbols found
Error executing link.exe.
A.exe - 2 error(s), 0 warning(s)

这就是说,在编译阶段,各个文件中定义的全局变量相互是透明的,编译A时觉察不到B中也定义了i,同样,编译B时觉察不到A中也定义了i。但是在链接阶段,要将各个文件的内容“合为一体”,因此,如果某些文件中定义的全局变量名相同的话,在链接阶段就会报重复定义(one or more multiply defined symbols)的错误。

因此,各个文件中定义的全局变量名不可相同。

在链接阶段,编译产生的obj文件合并了A、B两文件的内容,这也是出现int i重复定义错误的原因。

举个例子

一个文件中定义的全局变量,可以在整个程序的任何地方被使用,举例说,如果A文件中定义了某全局变量,那么B文件中也可以使用该变量。修改我们的程序,加以验证:

//A.cpp
void main()
{i = 100;  //试图使用B中定义的全局变量
}
//B.cpp
int i;

出现如下意料之中的编译错误,未定义int i错误(undeclared identifier Error),因为在链接之前A、B文件中的变量是彼此不可见的。

Compiling...
A.cpp
C:/Documents and Settings/wangjian/桌面/try extern/A.cpp(5) : error C2065:
'i' : undeclared identifier
Error executing cl.exe.
A.obj - 1 error(s), 0 warning(s)

编译器没有能够意识到,某个变量符号虽然不是本文件定义的,但是它可能是在其它的文件中定义的,为了避免错误的发生extern派上用场了。为上面的错误程序加上extern关键字后,顺利通过编译,链接,代码如下:

//A.cpp
extern int i;
void main()
{  i = 100; //试图使用B中定义的全局变量
}
//B.cpp
int i;

在C 文件中调用C方式编译的函数

相对于C,C 中新增了诸如重载等新特性,它们的编译有一些重要区别。将下面的小程序分别按C和C 方式编译,来探讨两种编译方式的区别。

int i;
int func(int t)
{return 0;
}
void main()
{
}

以C方式编译的结果如下:

COMM   _i  :  DWORD
PUBLIC   _func
PUBLIC   _main

以C 方式编译的结果如下:

PUBLIC  ?i@@ 3HA     ; i
PUBLIC  ?func@@YAHH@Z  ; func
PUBLIC  _main

可见,C方式编译下,变量名和函数名之前被统一加上了一个下划线,而C 编译后的结果却复杂的多,i变成了?i@@ 3HA ,func变成了?func@@YAHH@Z。C 中的这种看似复杂的命名规则是为C 中的函数重载,参数检查等特性服务的。

不同编译方式下的函数调用

如果在工程中,不仅有CPP文件,还有以C方式编译的C文件,函数调用就会有一些微妙之处。有如下CPP文件A.CPP和C文件B.C两个文件。

//A.CPP
void func();
void main()
{func();
}
//B.C
void func()
{
}

对A.CPP和B.C分别编译,都没有问题,但是链接时出现错误,原因就是C和CPP不同的编译方式产生的冲突。比如在上文中提到,C方式编译下,变量名和函数名之前被统一加上了一个下划线,而C 编译后的结果却复杂的多,i变成了?i@@ 3HA。

linking...
A.obj : error LNK2001: unresolved external symbol "void __cdecl func(void)" (?func@@YAXXZ)
Debug/A.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
A.exe - 2 error(s), 0 warning(s)

此时,可以通过extern关键字,来帮助编译器解决上面提到的问题。对于本例,只需将A.CPP改成如下代码即可:

//A.CPP
extern "C"
{void func(); //引入C语言方式编译的函数或变量
}
void main()
{func();
}

声明:

本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。

C/C 语言中extern的用法相关推荐

  1. C语言中extern的用法--转

    http://blog.sina.com.cn/s/blog_52deb9d50100ml6y.html 在C语言中,修饰符extern用在变量或者函数的声明前,用来说明"此变量/函数是在别 ...

  2. C语言中extern关键字用法

    一. 修饰变量,作为外部变量声明 一句话总结:扩充了全局变量的作用域,外部变量是在函数外部定义的全局变量,它的作用域是从变量的定义处开始,到本程序文件的末尾.如果外部变量不再文件的开头定义,其有效作用 ...

  3. c语言中extern变量,C语言中的Extern用法

    C语言中的Extern用法 (2010-07-28 12:50:39) 标签: 杂谈 分类: 技术 C语言中的Extern用法 网上有很多帖子问C语言中Extern的用法,而且回答的详细程度各尽不同. ...

  4. c语言typedef怎么自定义函数,c语言中typedef的用法

    C语言是一门通用计算机编程语言,应用广泛.C语言的设计目标是提供一种能以简易的方式编译.处理低级存储器.产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言. 尽管C语言提供了许多低级处理的功 ...

  5. c语言 strcpy作用,c语言中strcpy的用法

    c语言中strcpy的用法的用法你知道吗?下面小编就跟你们详细介绍下c语言中strcpy的用法的用法,希望对你们有用. c语言中strcpy的用法的用法如下: strcpy原型声明:extern ch ...

  6. c语言中getche的用法,c语言中getch的用法

    [www.hywsbj.com--图表展板] getch()函数是无回显的从控制台取得一个字符.以利用getch()函数让程序调试运行结束后等待编程者按下键盘才返回编辑界面,即任意键继续效果.下面小编 ...

  7. C语言中extern关键字的使用

    C语言中extern关键字的使用,直接上代码. file1.c文件 #include<stdio.h> extern long power(int); int A = 2; int mai ...

  8. php indexof的用法,c语言中indexof的用法有哪些

    c语言中indexof的用法有哪些 index在互联网上表示网站的默认主页.一般为 index.html index.htmindex.aspindex.php:另外的默认主页也多用default.h ...

  9. c语言中point的用法_关于C语言Switch语句,先学这些技巧够不够?

    一.C语言中switch的用法 1.switch后面括弧内的[表达式],ANSI标准允许它为任何类型: 2.当表达式的值与某一个case后面的常量表达式的值相等时,就执行此case后面的语句,否则,就 ...

最新文章

  1. opengl代码实例_OpenGL-打开一个窗口
  2. html运用以及工具
  3. 高性能计算机 和服务器,一种高性能计算机服务器
  4. mysql binlog线程恢复_使用MySQL SQL线程回放Binlog实现恢复
  5. mac删除android sd卡,如何从mac完全删除android及其所有文件?
  6. root用户登录mysql后新建用户提示1045错误
  7. golang mysql 插入_Mysql学习(一)添加一个新的用户并用golang操作Mysql
  8. Python:SyntaxError: unexpected EOF while parsing
  9. 算法分析与设计实验报告——实现哈夫曼编码
  10. RA8835驱动320240液晶模块例程
  11. 当前网络安全风险及举例
  12. Prince和学生们侃侃而谈系列01
  13. 运筹优化学习07:Lingo的 @if 函数的使用方法
  14. 2021-01-16 SONiC系统管理10 Telemetry
  15. TeamViewer和向日葵远控软件的个人使用感觉
  16. AIR开发ios游戏总结
  17. Android中播放本地SD卡中歌曲须要的加入的权限
  18. 计算二分类的特异性和灵敏度
  19. linux基本功之df命令实战
  20. echarts-gl 使用出现错误

热门文章

  1. 部署Spring Boot Angular App(Maven和Tomcat)的4种方法
  2. Spring Bootstrap中带有配置元数据的高级配置
  3. 在Java8中包装设计模式
  4. 都灵JVM编程语言:使用ANTLR构建高级词法分析器
  5. 在Spring使用AWS SQS创建消息驱动Bean
  6. Apache Cassandra和低延迟应用程序
  7. 我的Wiki:使用JConsole对WildFly(或JBoss AS7)进行远程JMX访问
  8. 如何为每个URL连接设置自定义SSLSocketFactory的TrustManager
  9. 跟踪异常–第5部分–使用Spring进行计划
  10. Java 8 – Date API的新增功能