C语言外部变量的使用以及erxtern的用法
网上有很多帖子问C语言中extern的用法,而且回答的详细程度各尽不同. 所以我就像写一篇博文来谈谈我对extern的看法,不一定十分恰当,只当大家共勉.
变量定义性声明和引用性声明变量的声明有两种情况:
1、一种是需要建立存储空间的。
例如:int a 在声明的时候就已经建立了存储空间。
2、另一种是不需要建立存储空间的。
例如:extern int a 其中变量a是在别的文件中定义的。
前者是“定义性声明(defining declaration)”或者称为“定义(definition)”,而后者是“引用性声明(referncing declaration)”或者简成为“声明(Declaration)”,从广义的角度来讲声明中包含着定义,即定义是声明的一个特例,所以并非所有的声明都是定义
例如:int a; // 它既是声明,同时又是定义。 然而对于 extern int a;// 来讲它只是声明不是定义。 extern int a = 10; // 定义一个变量,同时初始化为10,只是定义不再是声明 注意: 由于C语言中定义变量的默认存储类型是extern的 int a = 10; 等价于 extern int a = 10; // 只是定义不是声明,但是extern int a = 10;作为定义在gcc下会有警告
一般的情况下我们常常这样叙述,把建立空间的声明称之为“定义”,而把不需要建立存储空间的声明称之为“声明”。很明显我们在这里指的声明是范围比较窄的,即狭义上的声明,也就是说非定义性质的声明
变量的声明和定义与extern在具体到extern的用法之前,有两个概念必须要能分清楚:
声明(Declaration)和定义(Definition)之间的区别.
声明一个变量只是宣布这个变量的属性,也就是说告诉编译器这个变量时什么类型(如int, long, string 等).
而定义一个变量不仅是声明了变量的属性,同时也告诉编译器给变量分配相应的存储空间.
在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。
extern修饰变量的声明。举例来说,如果文件main.c需要引用extern.c中变量int value,就可以在main.c中声明extern int value,然后就可以引用变量value。
这里需要注意的是,被引用的变量v的链接属性必须是外链接(external)的,也就是说main.c要引用到value,不只是取决于在main.c中声明extern int value,还取决于变量value本身是能够被引用到的。这涉及到c语言的另外一个话题--变量的作用域。能够被其他模块以extern修饰符引用到的变量通常是全局变量。还有很重要的一点是,extern int value可以放在main.c中的任何地方,比如你可以在main.c中的函数fun定义的开头处声明extern int value,然后就可以引用到变量value了,只不过这样只能在函数fun作用域中引用value罢了,这还是变量作用域的问题。对于这一点来说,很多人使用的时候都心存顾虑。好像extern声明只能用于文件作用域似的。
总结起来可以这样说,声明只是告诉编译器声明的变量和函数是存在的,但并没有真正分配空间给它,所以当后面的代码用到前面声明的变量或函数时,编译器在编译的时候不会报错。链接的时候编译器会去寻找这些变量和函数的内存地址,如果只声明了但没定义,链接器当然找不到它们了,所以就会报错。而对它们进行定义了的话,编译器就会给它们分配空间,它们就有自己的地址了,这时就能链接了。定义是要分配空间的,且定义只能有一次。而声明不分配空间,可以声明多次。
从本质上来讲,变量和函数没有区别。函数名是指向函数二进制块开头处的指针。如果文件main.c需要引用extern.c中的函数,比如在extern.c中原型是int fun(int num),那么就可以在main.c中声明extern int fun(int num),然后就能使用fun来做任何事情。就像变量的声明一样,extern int fun(int mu)可以放在main.c中任何地方,而不一定非要放在main.c的文件作用域的范围中。
对其他模块中函数的引用,最常用的方法是包含这些函数声明的头文件。
extern的引用方式比包含头文件要简洁得多!extern的使用方法是直接了当的,想引用哪个函数就用extern声明哪个函数。这大概是KISS原则的一种体现吧!这样做的一个明显的好处是,会加速程序的编译(确切的说是预处理)的过程,节省时间。在大型C程序编译过程中,这种差异是非常明显的。
extern修饰符可用于指示C或者C++函数的调用规范比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原因是C++和C程序编译完成后在目标代码中命名规则不同。
总结关键字extern用来声明一个变量(或函数),并指出它具有外部链接(它的名字在其它文件里是可见的)。被extern修饰的变量,其生存期为程序运行的整个过程(它在程序开始运行时被分配内存,在程序运行结束时才被收回)。被extern声明的变量(或函数)将在同一文件的后续部分定义,或定义在其它的源文件中。
在C语言中,关键字extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。关键字extern用于变量的声明:
示例extern.c
/********************************************************** File Name: extern.c Author: GatieMe Mail: gatieme@163.com Created Time: 2015年03月27日 星期五 16时11分50秒 *********************************************************/ #include stdio.h #include stdlib.h extern int ex_num = 20; // 作为变量定义会有警告 int num = 30; int value; char str[81] = "abcdefg";
Created Time: 2015年03月27日 星期五 16时12分14秒 *********************************************************/ #include stdio.h #include stdlib.h
extern int ex_num; // 声明一个外部变量,定义时2使用extern int ex_num = 20; extern int value; // 声明一个外部变量,定义时使用int value; extern char str[81]; int a; // 既是声明也是定义 extern int b; // 只是声明不是定义 int c = 10; // 只是定义不是声明 extern int d = 20; // 只是定义不是声明, 但是作为变量定义会有警告
相关文章
- C语言---变量与函数
- 【C语言入门教程】4.4 指针 与 指针变量
- C语言/C++常见习题问答集锦(十)
- C语言/C++常见习题问答集锦(一)
- [C语言]使用函数
- ZZNUOJ_C语言1052:前n项和(完整代码)
- ZZNUOJ_C语言1063:最大公约与最小公倍(完整代码)
- ZZNUOJ_C语言1078:a+b(多实例测试1)
- ZZNUOJ_C语言1016:银行利率(完整代码)
- 【C语言】指针应用
- 一起talk C栗子吧(第一百二十三回:C语言实例--显示变量和函数的地址)
- C语言之基本算法33—矩阵的基本运算
- 练习 1-24 编写一个程序,查找C语言程序中的基本语法错误,如圆括号、方括号、花括号不配对等。
- C语言之自定字符串查找
- C语言char s[] 和 char *s的差别
- C语言使用技巧(六):memcpy函数为数组、函数变量和结构体内部的数组赋值
- C语言之信号屏蔽和捕获(六十)
- C语言之1ULL/1UL/1L区别(五十五)
- C语言之数据结构基本概览(四十六)
- C语言获取文件SHA1哈希
- C语言逆向——指针,函数指针,数组指针是比较难理解的,结构体指针要体会其编译器生成汇编代码的本质