关于extern的问题

例:

两个文件:

c文件:C.c

 

 

***********************************************

int external=5;                                               //全局变量,缺省为extern。
int func()                                                        //全局函数,缺省为extern。
{
return external;
}

***********************************************

cpp文件:CPP.cpp

***********************************************

#include "iostream"
using namespace std;

#ifdef __cplusplus
extern "C"
{
#endif
extern int external;             //告诉编译器extern是在别的文件中定义的int,这里并不会为其分配存储空间
extern int func();                //虽然这两个都是在extern "C"的{}里,但是仍然要显式指定extern,否则报错。
#ifdef __cplusplus             //不仅仅是函数,变量也要放在extern "C"中。
}
#endif


void main(void)
{
cout<<"the value of external in c file is: "<<external<<endl;
external=10;
cout<<"after modified in cpp is : "<<func()<<endl;
}

***********************************************

在讨论extern "C"之前先来讨论extern。

1、C/C++里全局变量和全局函数的定义缺省是extern的。即如果一个project由好几个文件组成,那么在A文件的全局作用域中定义了全局变量或者全局函数,默认情况下在其他文件中是可见的,即其他的文件只要在自己的全局作用域中用extern显式声明A中的全局变量和函数,就可以使用A中定义的全局变量和全局函数。

2、需要注意的一点是,extern int external 这样的声明并不为external分配内存空间。这里只是一个声明,它告诉编译器 external 这个变量是在其他文件中定义。因此,在编译的时候即使找不到external的定义也不会报错,因为连接的时候会在其他文件的obj中找到external。

3、cout<<"the value of external in c file is: "<<external<<endl;
    external=10;
      cout<<"after modified in cpp is : "<<func()<<endl;

     用这三句代码来说明extern:变量external是在C.c文件中定义的,CPP.cpp只是声明了一下,它告诉编译器CPP中用到的external是在别的文件中定义的。首先,打印出external的值,为5(C文件中定义externl为5,这更加说明了CPP中并不为external开辟新空间,否则应该为0),然后,在CPP文件中将external改为10,通过调用func()显式external的值。func()是C中的函数,它返回external的值,结果打印出10(进一步说明了external定义在C,使用在CPP)。

4、声明的时候,如果去掉变量前面的extern,将会出现连接错误,提示定义了两个同名变量。

5、与extern对应的是static。在全局作用域里用static显式声明的变量和函数说明它们只能供其所在的文件使用,其他文件对其不可见;如果是在模块中声明一个static变量,则这个变量的作用域还是所在模块,但是生命周期延长到程序结束。

再来看extern "C"。

extern "C" 的引用就是为了解决C++语言和C语言的混合编程问题。

C++支持的函数重载机制导致了C和C++编译机制的不同。

比如对一个函数

                        void foo( int x, int y );

由C编译器编译后符号库中的名字为_foo;而C++编译器编译后则为_foo_int_int,称为mangled name。C++正是靠这种编译机制实现了重载,比如另有一个重载函数void foo( int x, floaty );则编译后符号库中的名字为_foo_int_float。

这样就容易理解了,一个用C编写和编译的函数,如果需要在一个C++程序中调用和使用它,必须用extern "C",因为extern "C"能够保证对调用的C函数采用C的方式对其进行编译;否则,由于编译后符号库的名字不匹配,连接器在C的obj中找不到匹配的函数,则出现连接错误。

值得注意的是:不仅仅是全局函数,使用C中定义的全局变量也要放在extern "C"的{}中。

extern "C"中也可以添加整个C的头文件(#include)。

由于C不支持extern "C",所以出现了源文件中的条件编译语句(#ifdef...#endif)。

查看obj文件中符号库的方法:

vc安装目录的bin目录下有个应用程序dumpbin.exe。用如下命令行语句:

dumpbin.exe filename.obj /symbols /out:show.txt     ( /out:show.txt 是将输出结果重定向到show.txt文件)

<think>好的,用户现在问的是关于extern的错误事例。之前他们问过声明和定义的关系,现在可能在实际编码中遇到了问题,想通过具体例子来理解extern的错误用法。首先,我需要回忆一下extern的常见错误场景,比如重复定义、声明和定义不一致、忘记定义等。 用户可能是在项目中出现链接错误,比如多个文件定义了同一个变量,或者声明了extern但没实际定义,导致链接器找不到。需要举一些典型的例子,说明这些错误是如何发生的,以及如何解决。 另外,用户可能对extern的理解还不够深入,尤其是在多文件项目中如何正确使用。需要确保例子覆盖不同情况,比如变量、函数,还有头文件中的错误用法。还要注意单一定义规则(ODR),因为extern使用不当很容易违反这个规则。 可能用户还分不清声明和定义的区别,尤其是在使用extern时,容易混淆。比如,在头文件中使用extern声明变量,但在源文件中没有定义,或者多个源文件重复定义。这些都是常见的错误点。 接下来,要组织这些例子,每个例子说明问题、错误代码、错误原因和解决方法。同时,总结注意事项,帮助用户避免常见陷阱。这样他们就能更好地理解如何正确使用extern,避免链接错误和重复定义的问题。</think>在 C++ 中,`extern` 关键字用于声明一个变量或函数,表示其定义在其他文件中。但若使用不当,会导致编译或链接错误。以下是几个常见的 **`extern` 错误事例**及其分析: --- ### **1. 重复定义(违反单一定义规则)** #### **错误代码**: ```cpp // File1.cpp extern int a = 10; // 错误:extern 变量不应直接初始化(实际是定义) // File2.cpp int a = 20; // 定义 ``` #### **错误原因**: - `extern int a = 10` 看似是声明,但初始化操作使其成为**定义**。 - 多个文件中对 `a` 进行了重复定义,违反单一定义规则(ODR),导致链接错误。 #### **修复方法**: - 正确的 `extern` 声明不初始化变量: ```cpp // File1.cpp extern int a; // 仅声明,不定义 // File2.cpp int a = 20; // 唯一定义 ``` --- ### **2. 声明与定义类型不匹配** #### **错误代码**: ```cpp // FileA.cpp extern double value; // 声明为 double 类型 // FileB.cpp int value = 100; // 定义为 int 类型 ``` #### **错误原因**: - 声明 (`extern double value`) 和定义 (`int value`) 的**类型不一致**。 - 编译器可能通过,但链接时会导致未定义行为(如内存解释错误)。 #### **修复方法**: - 确保声明和定义的类型一致: ```cpp // FileA.cpp extern int value; // 声明为 int // FileB.cpp int value = 100; // 定义 ``` --- ### **3. 忘记定义 extern 变量** #### **错误代码**: ```cpp // Header.h extern int missingVar; // 声明 // Main.cpp #include "Header.h" int main() { missingVar = 5; // 错误:未找到定义 return 0; } ``` #### **错误原因**: - 使用 `extern` 声明了变量 `missingVar`,但**未在任何源文件中定义**。 - 导致链接错误:`undefined reference to missingVar`。 #### **修复方法**: - 在某个源文件中提供定义: ```cpp // Source.cpp int missingVar = 0; // 定义 ``` -- ### **4. 在头文件中错误使用 extern** #### **错误代码**: ```cpp // Header.h extern int headerVar = 42; // 错误:在头文件中初始化 extern 变量 // File1.cpp #include "Header.h" // File2.cpp #include "Header.h" ``` #### **错误原因**: - 在头文件中使用 `extern int headerVar = 42` 实际是定义变量,导致每个包含该头文件的源文件都包含 `headerVar` 的定义,违反 ODR。 - 链接错误:`multiple definition of headerVar`。 #### **修复方法**: - 头文件中仅声明,源文件中定义: ```cpp // Header.h extern int headerVar; // 仅声明 // Source.cpp int headerVar = 42; // 唯一定义 ``` -- ### **5. 对非 extern 变量重复声明** #### **错误代码**: ```cpp // File1.cpp int sharedVar = 100; // 定义 // File2.cpp int sharedVar = 200; // 重复定义(未用 extern 声明) ``` #### **错误原因**: - 两个文件都直接定义了 `sharedVar`,未使用 `extern` 声明,导致重复定义。 - 链接错误:`multiple definition of sharedVar`。 #### **修复方法**: - 在一个文件中定义,其他文件中用 `extern` 声明: ```cpp // File1.cpp int sharedVar = 100; // 唯一定义 // File2.cpp extern int sharedVar; // 声明 ``` --- ### **6. 函数声明与 extern 混淆** #### **错误代码**: ```cpp // File1.cpp extern void func(); // 正确:函数声明默认带有 extern // File2.cpp void func() { ... } // 正确:定义 // File3.cpp extern void func() { ... } // 错误:extern 函数不能直接定义(除非是内联) ``` #### **错误原因**: - 在 `File3.cpp` 中尝试用 `extern` 定义函数,导致重复定义(除非使用 `inline` 关键字)。 #### **修复方法**: - 仅在头文件中声明函数,在单个源文件中定义: ```cpp // Header.h void func(); // 声明 // File2.cpp void func() { ... } // 定义 ``` -- ### **总结:extern 的注意事项** 1. **禁止初始化**:`extern` 声明变量时不能初始化(否则变成定义)。 2. **单一定义**:确保每个 `extern` 变量在全局作用域中只有一处定义。 3. **类型一致性**:声明和定义的变量类型必须严格一致。 4. **头文件规则**:头文件中用 `extern` 声明变量,源文件中定义。 5. **函数默认 extern**:函数声明默认是 `extern` 的,无需显式写出(除非需要限制可见性)。 正确使用 `extern` 可以避免重复定义错误,实现多文件间的变量共享。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值