c语⾔中外部变量的使⽤⽅法,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 等).
⽽定义⼀个变量不仅是声明了变量的属性,同时也告诉编译器给变量分配相应的存储空间.
extern的⽤法详解
在C语⾔中,修饰符extern⽤在变量或者函数的声明前,⽤来说明“此变量/函数是在别处定义的,要在此处引⽤”。
extern修饰变量的声明。
举例来说,如果⽂件main.c需要引⽤extern.c中变量int value,就可以在main.c中声明extern int value,然后就可以引⽤变量value。
这⾥需要注意的是,被引⽤的变量v的链接属性必须是外链接(external)的,也就是说main.c要引⽤到v
alue,不只是取决于在main.c中声明extern int value,还取决于变量value本⾝是能够被引⽤到的。这涉及到c语⾔的另外⼀个话题--变量的作⽤域。能够被其他模块以extern修饰符引⽤到的变量通常是全局变量。还有很重要的⼀点是,extern int value可以放在main.c中的任何地⽅,⽐如你可以在main.c 中的函数fun定义的开头处声明extern int value,然后就可以引⽤到变量value了,只不过这样只能在函数fun作⽤域中引⽤value罢了,这还是变量作⽤域的问题。对于这⼀点来说,很多⼈使⽤的时候都⼼存顾虑。好像extern声明只能⽤于⽂件作⽤域似的。
总结起来可以这样说,声明只是告诉编译器声明的变量和函数是存在的,但并没有真正分配空间给它,所以当后⾯的代码⽤到前⾯声明的变量或函数时,编译器在编译的时候不会报错。链接的时候编译器会去寻这些变量和函数的内存地址,如果只声明了但没定义,链接器当然不到它们了,所以就会报错。⽽对它们进⾏定义了的话,编译器就会给它们分配空间,它们就有⾃⼰的地址了,这时就能链接了。定义是要分配空间的,且定义只能有⼀次。⽽声明不分配空间,可以声明多次。
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的使⽤⽅法是直接了当的,想引⽤哪个函数就⽤extern声明哪个函数。这⼤概是KISS 原则的⼀种体现吧!这样做的⼀个明显的好处是,会加速程序的编译(确切的说是预处理)的过程,节省时间。在⼤型C程序编译过程中,这种差异是⾮常明显的。
extern修饰符可⽤于指⽰C或者C++函数的调⽤规范
⽐如在C++中调⽤C库函数,就需要在C++程序中⽤extern “C”声明要引⽤的函数。这是给链接器⽤的,告诉链接器在链接的时候⽤C 函数规范来链接。主要原因是C++和C程序编译完成后在⽬标代码中命名规则不同。
总结
关键字extern⽤来声明⼀个变量(或函数),并指出它具有外部链接(它的名字在其它⽂件⾥是可见的)。被extern修饰的变量,其⽣存期为程序运⾏的整个过程(它在程序开始运⾏时被分配内存,在程序运⾏结束时才被收回)。被extern声明的变量(或函数)将在同⼀⽂件的后续部分定义,或定义在其它的源⽂件中。
在C语⾔中,关键字extern⽤在变量或者函数的声明前,⽤来说明“此变量/函数是在别处定义的,要在此处引⽤”。关键字extern⽤于变量的声明:
⽰例
extern.c
c语言char的用法/********************************************************** > File Name: extern.c > Author: GatieMe > Mail: gatieme@163 > Created Time: 2015年03⽉27⽇ 星期五 16时11分50秒 *********************************************************/
#include
#include
extern int ex_num = 20; // 作为变量定义会有警告
int num = 30;
int value;
char str[81] = "abcdefg";
main.c
/********************************************************** > File Name: main.c > Author: GatieMe > Mail: gatieme@163 > Created Time: 2015年03⽉27⽇ 星期五 16时12分14秒 *********************************************************/
#include
#include
extern int num; // 声明⼀个外部变量,定义时使⽤int num = 30;
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; // 只是定义不是声明, 但是作为变量定义会有警告int main(void)
{
printf("num = %d\n", num);
printf("ex_num = %d\n", ex_num);
printf("value = %d\n", value);
printf("str = %s\n", str);
printf("a = %d\n", a);
// printf("%d\n", b); // ERROR, 链接错误,不到变量定义
printf("c = %d\n", c);
printf("d = %d\n", d);
return EXIT_SUCCESS;
}
Makefile
#Makefile
main:extern.o main.o
gcc $^ -o $@
extern.o:extern.c
gcc -c $^ -o $@
main.o:main.c
gcc -c $^ -o $@
clean:
rm extern.o main.o
rm main
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论