C++ extern的解析

477 阅读3分钟
  • 关键字 extern 可以应用于全局变量、函数或模板声明。它指定符号具有 external 链接。

  • 关键字 extern 具有四种含义(补一个局部变量的),具体取决于上下文:

    • 在非 const 全局变量声明中,extern 指定变量或函数在另一个转换单元中查找定义。 必须在除定义变量的文件之外的所有文件中应用 extern。
    • 在 const 变量声明中,它指定变量具有 external 链接。 extern 必须应用于所有文件中的所有声明。 (默认情况下,全局 const 变量具有内部链接。)
    • 对于局部变量来说,extern可用于声明该局部变量来自其他转换单元,但是不能使用extern定义一个拥有外部链接的局部单元。(这也是为什么在函数体内定义extern修饰的变量会报错)参考:blog.csdn.net/deatharthas…
    • extern "C" 指定函数在别处定义并使用 C 语言调用约定。 extern "C" 修饰符也可以应用于块中的多个函数声明。

      • 可以将代码声明成C风格

        • 使C++能够调用C语言的代码:

          • 声明一个C风格的函数:extern "C" int func();
          • 声明一堆C风格的函数:extern "C"{ int func1(); int func2();...}
          • 声明引用的头文件是C风格:extern "C"{ #include "a.h" #include "b.h" ...}
        • 在C中调用C++代码:

          • C语言会将函数编译为_函数名的形式,因此调用时会找_函数名。与C++的约定不同,因此C中不能正常使用C++中的函数。
          • 因为C语言环境不认extern "C",因此要在C中调用C++的函数需要将该函数声明为C形式。但若在头文件中写extern "C",C的源文件引用该头文件时又会报错。

            • C++环境中默认定义了一个宏:__cplusplus,因此只能根据这个宏来判断是在哪个环境下,是否该加extern "C"。如下图,头文件被.c引用,extern "C"为灰色,按C的风格使用。
          • 声明为C风格的函数,不支持重载。对C语言来说,重载的函数都会被翻译成_函数名。
        • tip:C和C++混用时,源文件不要重名,因为源文件会被编译成.obj文件,重名就只能保留最新的。
    • 在模板声明中,extern 指定模板已在其他位置实例化。 extern 告知编译器它可以重复使用另一个实例化,而不是在当前位置创建新实例。 有关使用 extern 的详细信息,请参阅显式实例化
  • extern的理解,参考blog.csdn.net/gerks/artic…

    • 理解extern关键在于是extern是声明而不是在定义,其变量和函数的定义别的转换单元中,extern提示编译器遇到此变量和函数时在其他模块中寻找其定义。
    • 函数本身就是extern的因此加不加extern修饰均可。全局变量在外部使用声明时,extern关键词是必须的,否则就成了本转换单元中的变量定义。而局部变量的声明不能有extern的修饰,且局部变量在运行时才在堆栈中分配内存。
    • extern的使用最常见的用法就是在声明文件即头文件(.h)与定义文件即(.c/.cpp),我们在头文件(.h)中用extern声明某个变量或者函数为外部变量或者函数,在.cpp/.c文件中定义函数或者变量。然后我们在其他文件或者工程中使用该.cpp/.c文件中定义的函数或者变量时,只需#include<该头文件>即可。因为你在头文件中用extern声明的某个变量或者函数,将在本工程或者函数中预编译时展开该头文件。也即相当于实现了本工程或者本文件的自己声明extern某变量或者函数。