代码改变世界

[转]C/C++ extern详解

2011-10-22 11:45  zhiyzhan  阅读(139)  评论(0)    收藏  举报

转自:http://blog.csdn.net/lwbeyond/article/details/6579512

1.   基本解释
   extern可以置于变量或者 函数 前,以标示变量或者 函数 的定义在别的文件中,提示编译器遇到此变量和 函数 时在其他模块中寻找其定义。
  另外,
extern也可用来进行链接指定。


2.  extern 变量

extern int a;
  仅仅是一个变量的声明,其并不是在定义变量
a ,并未为 a分配内存空间。变量 a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。

通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字 extern声明。例如,如果模块 B欲引用该模块 A中定义的全局变 量和函数时只需包含模块 A的头文件即可。这样,模块 B中调用模块 A中的函数时,在编译阶段,模块 B虽然找不到该函数,但是并不会报错;它会在连接阶段中从 模块 A 编译生成的目标代码中找到此函数


  如查在源文件里定义了一个数组:
char a[6];
  在另外一个文件里用下列语句进行了声明:
extern char *a
  请问,这样可以吗?

     答案与分析:
 
   不可以,程序运行时会告诉你非法访问。原因在于,指向类型 T 指针 并不等价于类型 T的数组。 extern char *a声明的是一个 指针 变量而不是字符数组,因此与实际的定义不同,从而造成运行时非法访问。应该将声明改为 extern char a[ ]


3. extern 函数
  常常见
extern放在 函数 的前面成为 函数 声明的一部分,那么, C 语言 的关键字 extern 函数 的声明中起什么作用?
  答案与分析:

  如果
函数 的声明中带有关键字 extern仅仅是暗示这个 函数 可能在别的源文件里定义,没有其它作用 。即下述两个 函数 声明没有明显的区别:
extern int f(); int f();
  当然,这样的用处还是有的,就是在程序中取代
include “xx.h” 来声明 函数 ,在一些复杂的项目中,我比较习惯在所有的 函数 声明前添加 extern修饰。

4.  extern “C”
  在
C++ 环境下使用 C函数 的时候,常常会出现编译器无法找到 obj模块中的 C函数 定义,从而导致链接失败的情况,应该如何解决这种情况呢?

答案与分析:
  
C++ 语言在编译的时候为了解决 函数 的多态问题 ,会将 函数 名和参数联合起来生成一个中间的 函数 名称,而 C 语言 则不会 ,因此会造成链接时找不到对应 函数 的情况,此时 C函数 就需要用 extern “C”进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间 函数 名。

 

下面是一个标准的写法:

  1. //在.h文件的头上  
  2. #ifdef __cplusplus  
  3. #if __cplusplus  
  4. extern "C"{  
  5.   #endif  
  6.   #endif /* __cplusplus */  
  7.   …  
  8.   …  
  9.   //.h文件结束的地方  
  10.   #ifdef __cplusplus  
  11.   #if __cplusplus  
  12. }  
  13. #endif  
  14. #endif /* __cplusplus */  


  实现
C++ C及其它语言的混合编程。


5. extern "C" 的惯用法

( 1) C++中引用 C语言中的函数和变量,在包含 C语言头文件(假设为 cExample.h)时,需进行下列处理:

extern "C"
{
#include "cExample.h"
}

而在 C语言的头文件中,对其外部函数只能指定为 extern 类型 C语言中不支持 extern "C"声明,在 .c文件中包含了 extern "C"时会出现编译语法错误。

   C++引用 C函数例子工程中包含的三个文件的源代码如下:

  1. /* c语言头文件:cExample.h */  
  2. #ifndef C_EXAMPLE_H  
  3. #define C_EXAMPLE_H  
  4. extern int add(int x,int y);  
  5. #endif  
  6. /* c语言实现文件:cExample.c */  
  7. #include "cExample.h"  
  8. int add( int x, int y )  
  9. {  
  10.             return x + y;  
  11. }  
  12.   
  13. // c++实现文件,调用add:cppFile.cpp  
  14. extern "C"  
  15. {  
  16. #include "cExample.h"  
  17. }  
  18. int main(int argc, char* argv[])  
  19. {  
  20. add(2,3);  
  21. return 0;  
  22. }  

  如果 C++调用一个 C语言编写的 .DLL时,当包括 .DLL的头文件或声明接口函数时,应加 extern "C" {  }


2)在 C中引用 C++语言中的函数和变量时, C++的头文件需添加 extern "C",但是在 C语言中不能直接引用声明了 extern "C"的该头文件,应该仅将 C文件中 C++中定义的 extern "C"函数声明为 extern类型。
  
C引用 C++函数例子工程中包含的三个文件的源代码如下:

  1. //C++头文件 cppExample.h  
  2. #ifndef CPP_EXAMPLE_H  
  3. #define CPP_EXAMPLE_H  
  4. extern "C" int add( int x, int y );  
  5. #endif  
  6.   
  7. //C++实现文件 cppExample.cpp  
  8. #include "cppExample.h"  
  9. int add( int x, int y )  
  10. {  
  11. return x + y;  
  12. }  
  13.   
  14. /* C实现文件 cFile.c 
  15. /* 这样会编译出错:#include "cExample.h" */  
  16. extern int add( int x, int y );  
  17. int main( int argc, char* argv[] )  
  18. {  
  19. add( 2, 3 );  
  20. return 0;