C++中extern关键字使用

文章出自:http://blog.csdn.net/sruru/article/details/7951019

chapter 1 . extern关键字的作用  

  extern是一个关键字,它告诉编译器存在着一个变量或者一个函数,如果在当前编译语句的前面中没有找到相应的变量或者函数,也会在当前文件的后面或者其它文件中定义,来看下面的例子。

   

[cpp]  view plain copy
  1. // extern.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <iostream>  
  6. using namespace std;  
  7.   
  8. extern int i;  
  9. extern void func();  
  10. int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t     _TCHAR;#define _tmain      wmain  
  11. {  
  12.     i = 0;  
  13.     func();  
  14.     return 0;  
  15. }  
  16.   
  17. int i;  
  18.   
  19. void func()  
  20. {  
  21.     i++;  
  22.     cout << "i = " << i << endl;  
  23. }  

 

    上面代码中变量i和函数func在文件末尾定义,所以变量需要使用extern关键字告诉编译器,变量在别的地方定义。extern int i我原来以为extern i就可以,结果编译器报错,仔细想下确实应该,否则编译器不知道i是什么类型的数据,又怎么能判断i = 0是否是一个正确的赋值语句呢?

 

    那么定义在其他文件中的函数和变量,如何通过extern关键字调用呢?

    首先,定义在其它文件中的函数和变量,可以使用两种方法调用:

        一、使用头文件调用,这时候,函数和变量必须在头文件中定义和声明。

        二、使用extern关键字调用,这时候函数和变量在.cpp或者.c文件中定义和声明。

    看下面两个例子:

    devVar.cpp函数中定义:

       

[cpp]  view plain copy
  1. #include "stdafx.h"  
  2.   
  3. int i;  


 

    extern.cpp中

[cpp]  view plain copy
  1. // extern.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <iostream>  
  6. using namespace std;  
  7.   
  8. extern int i;  
  9. extern void func();  
  10. int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t     _TCHAR;#define _tmain      wmain  
  11. {  
  12.     i = 0;  
  13.     func();  
  14.     return 0;  
  15. }  
  16.   
  17. void func()  
  18. {  
  19.     i++;  
  20.     cout << "i = " << i << endl;  
  21. }  


 

   编译工程,程序输出:i = 1,这里使用extern关键字声明在其它cpp文件中定义的变量和函数。

 

    #include <filensme> --- 将filename文件中的内容插入到新的文件中。

    deVar.h文件中代码为

[cpp]  view plain copy
  1. #include <stdio.h>  
  2.   
  3. int i = 1;  
  4.   
  5. void func()  
  6. {  
  7.     printf("%d",i++);  
  8. }  

     函数func修改全局变量i的值并输出。

    extern.cpp文件内容为:

[cpp]  view plain copy
  1. #include "stdafx.h"  
  2. #include <stdio.h>  
  3. #include <iostream>  
  4. using namespace std;  
  5. #include "devVar.h"  
  6. //extern int i;  
  7. //extern void func();  
  8.   
  9. int main(void)  
  10. {  
  11.     for (int x = 0;x < 10; x++)  
  12.     {  
  13.         func();  
  14.     }  
  15. }  

程序输出1,2,3,4,5,6,7,8,9,10,这里#include <filname.h> 包含定义在其它头文件中的函数和变量,在来看一个例子。

   

[cpp]  view plain copy
  1. // extern.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <iostream>  
  6. using namespace std;  
  7.   
  8. extern int i;  
  9. extern int  func(int);//这里extern必需的,函数定义在其它cpp文件中  
[cpp]  view plain copy
  1. int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t     _TCHAR;#define _tmain      wmain  
  2. {  
  3.     i = 100;  
  4.     func(i);  
  5.     return 0;  
  6. }  

    devVar.cpp文件中内容为:

   

[cpp]  view plain copy
  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. using namespace std;  
  4.   
  5. int i;  
  6.   
  7. int func(int a)  
  8. {  
  9.     i = a;  
  10.     cout << "i = " << i << endl;  
  11.     return 0;  
  12. }  


    这样,同样是输出了i= 100。

    能够使用extern引用其它cpp文件中定义的函数说明了一个问题:

    如果一个工程现编译cpp文件,在把多个目标文件链接成为可执行文件,而两个或多个文件中,定义了相同的全局变量,那么,程序编译的时候不会报错,因为编译器单独编译每个文件,在链接可执行文件的时候,由于多个目标文件中含有相同的全局变量,而生成可执行文件的时候,任何文件中定义的全局变量对其它目标文件都是可见的,此时由于变量定义冲突而发生错误。看下面的代码:

   

[cpp]  view plain copy
  1. // extern.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <iostream>  
  6. using namespace std;  
  7.   
  8. int i;  
  9. extern int  func(int);//这里extern是必须的函数定义在别的cpp文件中  
  10. int _tmain(int argc, _TCHAR* argv[])//typedef wchar_t     _TCHAR;#define _tmain      wmain  
  11. {  
  12.     i = 100;  
  13.     func(i);  
  14.     return 0;  
  15. }  


 

devVar.cpp文件中,内容为:

[cpp]  view plain copy
  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. using namespace std;  
  4.   
  5. int i;  
  6.   
  7. int func(int a)  
  8. {  
  9.     i = a;  
  10.     cout << "i = " << i << endl;  
  11.     return 0;  
  12. }  

    单独compile任何一个cpp文件都是对的,但是 编译工程,生成可执行文件的时候报错:

    1>LINK : D:\vctest\extern\Debug\extern.exe not found or not built by the last incremental link; performing full link
1>devVar.obj : error LNK2005: "int i" (?i@@3HA) already defined in extern.obj
1>D:\vctest\extern\Debug\extern.exe : fatal error LNK1169: one or more multiply defined symbols found

    原因是:两个.cpp文件中都定义了全局变量i,变量重复定义了。

 

    PS:定义在.h文件中的函数和变量不能使用extern变量声明,原因是#include <filename>在预编译的时候将.h文件中的内容插入了cpp文件中,因此编译器找得到在其它.h文件中定义的变量或者函数。编译的时候,只编译cpp文件的内容,.h文件时不参与编译,如果使用extern声明在.h文件中定义的变量或者函数,那么声明为extern的变量和函数在其它.cpp文件中找不到,因此程序编译的时候就发生了错误。

 

 

chapter2,如何混合编译C语言和C++

    实际开发过程中,C++中会调用C与语言编写的代码,我在网络上面找到一篇写得很好的文章

   http://blog.csdn.net/keensword/article/details/401114

   就着上面的例子,我使用C语言采用两种方法重写了一下。

   方法一、全局函数和变量在devVar.c文件中实现,在extern.cpp文件中使用extern关键字声明在devVar.c文件中定义的函数和变量。

   devVar.c文件的代码如下所示:

   

[cpp]  view plain copy
  1. #include <stdio.h>  
  2.   
  3. int i = 1;  
  4.   
  5. void func()  
  6. {  
  7.     printf("%d",i++);  
  8. }  

   extern.cpp文件中代码如下所示:

   

[cpp]  view plain copy
  1. #include "stdafx.h"  
  2. #include <stdio.h>  
  3. #include <iostream>  
  4. using namespace std;  
  5. //#include "devVar.h"  
  6. //extern int i;  
  7. //extern void func();  
  8.   
  9. extern "C"  
  10. {  
  11.     extern int i;  
  12.     extern void func();  
  13.     //#include "devVar.h"   
  14. }  
  15. int main(void)  
  16. {  
  17.     for (int x = 0;x < 10; x++)  
  18.     {  
  19.         func();  
  20.     }  
  21. }  

    所以在C++文件中编译C文件需要使用extern "C"关键字,声明语法如下所示

    extern "C"

    {

        采用C语言实现的内容

    }

 

    方法二、

    在devVar.h文件中实现C代码(即devVar.h作为C语言头文件),在.cpp文件中包含C语言头文件。

    devVar.h头文件内容为:

   

[cpp]  view plain copy
  1. #include <stdio.h>  
  2.   
  3. int i = 1;  
  4.   
  5. void func()  
  6. {  
  7.     printf("%d",i++);  
  8. }  

    extern.cpp文件内容如下所示

   

[cpp]  view plain copy
  1. #include "stdafx.h"  
  2. #include <stdio.h>  
  3. #include <iostream>  
  4. using namespace std;  
  5. //#include "devVar.h"  
  6. //extern int i;  
  7. //extern void func();  
  8.   
  9. extern "C"  
  10. {  
  11.     //extern int i;  
  12.     //extern void func();  
  13.     #include "devVar.h"   
  14. }  
  15. int main(void)  
  16. {  
  17.     for (int x = 0;x < 10; x++)  
  18.     {  
  19.         func();  
  20.     }  
  21. }  

    其中,包含C语言头文件的方式为:

[cpp]  view plain copy
  1. extern "C"  
  2. {  
  3.     //extern int i;  
  4.     //extern void func();  
  5.     #include "devVar.h"   
  6. }  

 

    写到这里,楼主又产生了一个疑问,上面的例子讲的是C++调用C实现的代码,那如果是C调用C++编写的代码呢?

    楼主作了如下改动:

    devVar.cpp代码为:   

[cpp]  view plain copy
  1. #include <stdio.h>  
  2.   
  3. int i = 1;  
  4.   
  5. void func()  
  6. {  
  7.     printf("%d",i++);  
  8. }  

    extern.c文件代码为

[cpp]  view plain copy
  1. #include <stdio.h>  
  2.   
  3. extern int i;  
  4. extern void func();  
  5.   
  6. int main(void)  
  7. {  
  8.     int x = 0;  
  9.     for (;x < 10; x++)  
  10.     {  
  11.         func();  
  12.     }  
  13. }  

    单独编译每个文件都通过,链接声称可执行文件的时候报错:

    1>extern.obj : error LNK2019: unresolved external symbol _func referenced in function _main,说明.c文件中extern void func(),按照C编译的规则,得到函数_func,而devVar.cpp文件采用C++编译方式,得到的函数为XX·!_func(具体楼主也不知道哈),这样链接的时候函数自然找不到,那怎么解决呢?

    需要在devVar.cpp中,明确调用extern "C"关键字,声明cpp文件中有关代码,需要按照C的方式来生成,修改devVar.cpp文件如下所示:

   

[cpp]  view plain copy
  1.     #include <stdio.h>  
  2.   
  3.     int i = 1;  
  4.   
  5.   
  6. extern "C" void func()  
  7.     {  
  8.         printf("%d",i++);  
  9.     }  

     此时,除了需要使用extern "C"声明编译的时候采用C方式编译外,.cpp文件中的代码可以按照C++方式编写,例如

     devVar.cpp按照下面方式写,也是正确的。

    

[cpp]  view plain copy
  1. #include "stdafx.h"  
  2. #include <iostream>  
  3. using namespace std;  
  4.   
  5. int i = 1;  
  6.   
  7. extern "C" void func()  
  8.     {  
  9.         cout << "i = " << i++ << endl;  
  10.     }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值