摘自:http://blog.csdn.net/fxjtoday/article/details/6021845

  如果想明白为什么需要extern, 需要从编译和链接讨论起,

  现代编译器一般采用按文件编译的方式,因此在编译时,各个文件中定义的全局变量是互相透明的,也就是说,在编译时,全局变量的可见域限制在文件内部。但是到了链接阶段,要将各个文件的内容“合为一体”,因此,如果某些文件中定义的全局变量名相同的话,会报错. 因此,各个文件中定义的全局变量名不可相同。

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

  所以上面两个文件编译是没有问题的, 但是到了链接就会报重名错误

  如果此时A.cpp里面要用到, B.cpp中定义的i, 应该怎么办?

  那么既然上面说了重复定义出错, 那就把A.cpp中的"int i;"定义直接去掉是否可以

  看起来好像可以的, 因为全局变量的作用域是整个源程序, 这边也许是很多人会产生疑问的地方, 既然全局变量和全局函数的作用域是整个源程序的, 为什么在其他的文件里面使用一定要先声明(这样的声明往往在.h文件中, 并在使用处include该.h, 记住include就是copy, 之所以要使用.h, 而不是直接写在.c中, 只是为了保证易维护性, 最终编译器会自动将.h copy到每个.c中)

  答案就在编译阶段, 过程是先编译后链接, 而在编译时只能知道本文件的内容, 编译器并不能预见到你这个变量或函数在其他文件里面被定义过. 只有到了链接阶段编译器产能看到其他的文件.

  所以如果不事先声明, 那么在编译阶段一定会报错找不到该变量或函数.此时就需要使用extern来声明变量。

  extern的原理很简单,就是告诉编译器:“你现在编译的文件中,有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量,你要放行!”

  多说一句, 在声明变量是必须要加extern, 而在声明函数时却不需要, 为什么

  上面说了, 声明只是简单的告诉编译器, 这个东西在其他地方定义过了, 你不用管了, 所以编译器不会为声明分配空间, 或做其他操作, 这和定义是有本质区别的, 必须要正确区分

  对于变量必须用extern才能区分定义和声明, 因为这是变量定义和声明的唯一区别

  而函数不需要extern也能区分处定义和声明, 有实现就是定义, 没有就是声明, 所以不需要再加extern

  这就是c的简洁之处, 不需要的就别写

  再多说一句, 在c中, 全局变量和函数都是默认对外可见的, 如果想变成仅当前文件可见, 必须加上static.

  对于函数, 默认和加上extern是等价的, 都是表示对外可见

  但是对于变量, 却不一样, 加上extern就变成声明了, 所以不能给定义加上extern

  所以对于extern有如下说法,

  用于变量,声明该变量在其它地方定义;
  用于函数定义, 表示全局可见(属于冗余的)

extern的困惑的更多相关文章

  1. [C]关于extern与struct

    问题 我曾经很困惑,就是在两个编译单元当中,如何把一个单元中声明的struct结构引入到另外一个单元中来,折腾了很久,后来发现这位大神的留言 不是这么用的…… 类型的定义和类型变量的定义不同,类型定义 ...

  2. 关于extern "C"(详细剖析)

    [目录] 引言 extern “C”的前世今生 小心门后的未知世界 Q&A c++调用c的方法 c调用c++的方法 在你工作过的系统里,不知能否看到类似下面的代码. 这好像没有什么问题,你应该 ...

  3. const,static,extern 简介

    const,static,extern 简介 一.const与宏的区别: const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. 执行时刻:宏是预编 ...

  4. const extern static 终极指南

    const extern static 终极指南 不管是从事哪种语言的开发工作,const extern static 这三个关键字的用法和原理都是我们必须明白的.本文将对此做出非常详细的讲解. co ...

  5. C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解

    前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.之前分享过一篇 C#进阶系列——WebApi接口传参不再困惑:传参详解  ...

  6. 16-static和extern关键字2-对变量的作用

    上一讲介绍了static和extern对函数的作用,static用来定义一个内部函数,不允许其他文件访问:extern用来定义和声明一个外部函数,允许其他文件访问.static和extern对变量也有 ...

  7. 15-static和extern关键字1-对函数的作用

    一.extern与函数 如果一个程序中有多个源文件(.c),编译成功会生成对应的多个目标文件(.obj),这些目标文件还不能单独运行,因为这些目标文件之间可能会有关联,比如a.obj可能会调用c.ob ...

  8. C#进阶系列——WebApi 接口参数不再困惑:传参详解

    前言:还记得刚使用WebApi那会儿,被它的传参机制折腾了好久,查阅了半天资料.如今,使用WebApi也有段时间了,今天就记录下API接口传参的一些方式方法,算是一个笔记,也希望能帮初学者少走弯路.本 ...

  9. 转:C++项目中的extern "C" {}

    引言 在用C++的项目源码中,经常会不可避免的会看到下面的代码: #ifdef __cplusplus extern "C" { #endif /*...*/ #ifdef __c ...

随机推荐

  1. 在eclipse.ini中指定jdk的方式

    在eclisep的安装目录,打开eclipse.ini文件,加上这么一行,如下红色所示,注意加在-Vmargs前面,这两种方式的区别是:第二种方式除了会有eclipse进程外还会启动个java进程. ...

  2. python 本地文档查看

    本地安装Python文档本地查看,在命令行中运行: python -m pydoc -p 1234 在浏览器中访问如下链接,就可以访问到本地文档: http://localhost:1234/ 本地文 ...

  3. ASP.NET中常用的字符串分割函数

    asp.net字符串分割函数用法 先来看个简单的实例 但是其数组长度却是25,而不是3.下面这种方法是先将“[111cn.net]”替换成一个特殊字符,比如$,在根据这个字符执行Split 例如下面我 ...

  4. python多线程ctrl-c退出问题

    场景: 经常会遇到下述问题:很多io busy的应用采取多线程的方式来解决,但这时候会发现python命令行不响应ctrl-c 了,而对应的java代码则没有问题: public class Test ...

  5. Unity3D文件读写

    这里主要是简单的文件读写,不推荐使用,最好用的还是PlayerPrefs. using UnityEngine; using System.Collections; using System.IO; ...

  6. redis高级实用特性

    1. 安全性 2. 主从复制 3. 事务处理 4. 持久化机制 5. 发布订阅消息 : 可以做一个消息系统 6. 虚拟内存的使用 一 . 安全性 设置客户端连接后进行任何其他指定前需要使用的密码 . ...

  7. The h.264 Sequence Parameter Set

    转债:  http://www.cardinalpeak.com/blog/the-h-264-sequence-parameter-set/ View from the Peak The h.264 ...

  8. Git Book 中文版 - Git的撤消操作 - 重置, 签出 和 撤消

    Git Book 中文版 - Git的撤消操作 - 重置, 签出 和 撤消 Git的撤消操作 - 重置, 签出 和 撤消 Git提供了多种修复你开发过程中的错误的方法. 方法的选择取决于你的情况: 包 ...

  9. WebService学习之四:关于JAX-WS 注释

    基于 XML 的 Web Service 的 Java API"(JAX-WS)通过使用注释来指定与 Web Service 实现相关联的元数据以及简化 Web Service 的开发.注释 ...

  10. UVA 11300 Spreading the Wealth

    题目大意:n个人手中有些金币,每个人可给相邻两个人一些金币,使得最终每个人手中金币数相同,求被转手的金币最少数 m为最终每个人手中的金币数,a1,a2,a3,...,an为每个人开始时手中的金币数,x ...