深入理解extern用法 2022-08-02 04:48 94阅读 0赞 ## **一、 extern做变量声明** ## ### l 声明extern关键字的全局变量和函数可以使得它们能够跨文件被访问。 ### 我们一般把所有的全局变量和全局函数的实现都放在一个\*.cpp文件里面,然后用一个同名的\*.h文件包含所有的函数和变量的声明。如: /*Demo.h*/ #pragma once extern inta; extern intb; intadd(inta,intb); /*Demo.cpp*/ #include "Demo.h" /*这句话写或者不写在本例中都行,不过建议不写*/ /*不写不会出问题,写了有些情况下会出问题,下面有解释*/ int a =10; int b =20; int add(intl,intr) { return l +r; } 如果将Demo.cpp写成了Demo.c,编译器会告诉你说无法解析的外部符号。 因为Demo.c里面的实现会被C编译器处理,然而C++和C编译器在编译函数时存在差异,所以会存在找不到函数的情况。 ### l 全局函数的声明语句中,关键字extern可以省略,因为全局函数默认是extern类型的。 ### ### **l 声明和定义** ### externint a; //属于声明 externint a = 10; //属于定义,同下 externcharg\_str\[\]="123456";//这个时候相当于没有extern 如果在一个文件里定义了char g\_str\[\] = "123456";在另外一个文件中必须使用extern char g\_str\[ \];来声明。不能使用extern char\* g\_str;来声明。extern是严格的声明。且extern char\* g\_str只是声明的一个全局字符指针。 **注:声明可以拷贝n次,但是定义只能定义一次。** ## **二、extern “C”** ## ### l extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。 ### **被extern "C"限定的函数或变量是extern类型的:** extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。记住,下列语句: extern int a; 仅仅是一个变量的声明,其并不是在定义变量a,并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。 通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数。 与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。 **实现C++与C及其它语言的混合编程:** 被extern"C"修饰的变量和函数是按照C语言方式编译和连接的,未加extern “C”则按照声明时的编译方式。 ### l extern "C"的惯用法 ### **(1)**在C++中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理: extern "C"\{ \#include "cExample.h" \} 而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern"C"声明,在.c文件中包含了extern"C"时会出现编译语法错误。 **(2)**在C中引用C++语言中的函数和变量时,C++的头文件需添加extern"C",但是在C语言中不能直接引用声明了extern"C"的该头文件,应该仅将C文件中将C++中定义的extern"C"函数声明为extern类型。 ## **三、 extern 和static** ## **(1)**extern表明该变量在别的地方已经定义过了,在这里要使用那个变量。 **(2)**static 表示静态的变量,分配内存的时候,存储在静态区,不存储在栈上面。 static作用范围是内部连接的关系这和extern有点相反。它和对象本身是分开存储的,extern也是分开存储的,但是extern可以被其他的对象用extern引用,而static不可以,只允许对象本身用它。具体差别首先,static与extern是一对“水火不容”的家伙,也就是说extern和static不能同时修饰一个变量;其次,static修饰的全局变量声明与定义同时进行,也就是说当你在头文件中使用static声明了全局变量后,它也同时被定义了;最后,static修饰全局变量的作用域只能是本身的编译单元,也就是说它的“全局”只对本编译单元有效,其他编译单元则看不到它,如: /*test1.h*/ #ifndef TEST1H #define TEST1H static char g_str[]="123456"; void fun1(); #endif /*test1.cpp*/ #include "test1.h" void fun1() { cout <<g_str<<endl; } /*test2.cpp*/ #include "test1.h" void fun2() { cout <<g_str<<endl; } 以上两个编译单元可以连接成功,当你打开test1.obj时,你可以在它里面找到字符串"123456",同时你也可以在test2.obj中找到它们,它们之所以可以连接成功而没有报重复定义的错误是因为虽然它们有相同的内容,但是存储的物理地址并不一样,就像是两个不同变量赋了相同的值一样,而这两个变量分别作用于它们各自的编译单元。也许你比较较真,自己偷偷的跟踪调试上面的代码,结果你发现两个编译单元(test1,test2)的g\_str的内存地址相同,于是你下结论static修饰的变量也可以作用于其他模块,但是我要告诉你,那是你的编译器在欺骗你,大多数编译器都对代码都有优化功能,以达到生成的目标程序更节省内存,执行效率更高,当编译器在连接各个编译单元的时候,它会把相同内容的内存只拷贝一份,比如上面的"123456",位于两个编译单元中的变量都是同样的内容,那么在连接的时候它在内存中就只会存在一份了,如果你把上面的代码改成下面的样子,你马上就可以拆穿编译器的谎言: /*test1.cpp*/ #include "test1.h" void fun1() { g_str[0]=''a''; cout <<g_str<<endl; } /*test2.cpp*/ #include "test1.h" void fun2() { cout <<g_str<<endl; } /*main.cpp*/ void main() { fun1();// a23456 fun2();// 123456 } 这个时候你在跟踪代码时,就会发现两个编译单元中的g\_str地址并不相同,因为你在一处修改了它,所以编译器被强行的恢复内存的原貌,在内存中存在了两份拷贝给两个模块中的变量使用。正是因为static有以上的特性,所以一般定义static全局变量时,都把它放在原文件中而不是头文件,这样就不会给其他模块造成不必要的信息污染,同样记住这个原则吧! ## **四、extern和const** ## C++中const修饰的**全局常量**具有跟static相同的特性,即它们只能作用于本编译模块中,且static修饰的是**全局变量**,但是const可以与extern连用来声明该常量可以作用于其他编译模块中,如externconst char g\_str\[\]; 然后在原文件中别忘了定义:const char g\_str\[\] = "123456"; 所以当const单独使用时它就与static相同,而当与extern一起合作的时候,它的特性就跟extern的一样了!所以对const我没有什么可以过多的描述,我只是想提醒你,const char\* g\_str = "123456" 与 const char g\_str\[\] ="123465"是不同的,前面那个const修饰的是char \*而不是g\_str,它的g\_str并不是常量,它被看做是一个定义了的全局变量(可以被其他编译单元使用), 所以如果你像让char\* g\_str遵守const的全局常量的规则,最好这么定义const char\* const g\_str="123456"。
相关 C++ extern c 用法 一、整体代码 01.cpp include <iostream> include <stdio.h> include "a r囧r小猫/ 2021年12月13日 23:25/ 0 赞/ 182 阅读
相关 深入理解ConcurrentMap.putIfAbsent(key,value) 用法 深入理解ConcurrentMap.putIfAbsent(key,value) 用法 2014年10月22日 22:26:46 [吴孟达][Link 1] 阅读数:99 深碍√TFBOYSˉ_/ 2022年02月13日 15:21/ 0 赞/ 170 阅读
相关 extern声明全局变量的用法 这篇文章主要讲解一下extern声明全局变量的一些用法,虽然知识点比较浅显,但是却容易犯错,仅与那些初学C++的朋友分享,希望没有让大牛们见笑。 extern最基本的用法是 一时失言乱红尘/ 2022年05月17日 08:12/ 0 赞/ 119 阅读
相关 深入理解extern用法 一、 extern做变量声明 l 声明extern关键字的全局变量和函数可以使得它们能够跨文件被访问。 我们一般把所有的全局变量和全局函数的实现都放在一个\.cpp 你的名字/ 2022年08月02日 04:48/ 0 赞/ 95 阅读
相关 extern用法 1 基本解释 extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。 另外,extern也可 桃扇骨/ 2022年08月06日 04:10/ 0 赞/ 61 阅读
相关 C语言中extern的用法 在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。 1. extern修饰变量的声明。举例来说,如果文件 系统管理员/ 2022年08月06日 06:10/ 0 赞/ 85 阅读
相关 C语言中extern的用法 在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。 1. extern修饰变量的声明。举例来说,如果 文件 亦凉/ 2022年08月20日 12:07/ 0 赞/ 81 阅读
相关 C语言中extern的用法 C语言中extern的用法 在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。 1. extern修饰变量的声 约定不等于承诺〃/ 2022年08月21日 15:56/ 0 赞/ 145 阅读
相关 C/C++中extern用法 1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定 悠悠/ 2022年08月27日 05:58/ 0 赞/ 80 阅读
还没有评论,来说两句吧...