extern关键字
extern
关键字的作用详解
在 C++ 中,extern
关键字的主要作用是用于声明变量或函数是 外部定义的,即它们的定义在另一个文件中。extern
通常用于引入外部符号(变量或函数)以供当前编译单元使用。以下是 extern
关键字的两个主要用途:
- 跨文件引用全局变量或函数。
- 与
extern "C"
一起使用,用于 C++ 和 C 代码之间的链接兼容。
1. extern
修饰符的基本用法
当 extern
用于标识变量或函数时,它告诉编译器该变量或函数的定义在另一个编译单元中(例如另一个 .cpp
文件)。这使得多个编译单元可以共享全局变量或函数。
例子:
- 文件1:
file1.cpp
1 |
|
- 文件2:
file2.cpp
1 |
|
解释:
- 在
file1.cpp
中,变量g_Int
和函数printGlobal
被定义。 - 在
file2.cpp
中,我们使用extern
声明g_Int
和printGlobal
。这告诉编译器它们的定义在另一个编译单元中(即file1.cpp
),并在链接阶段解决符号。
编译和链接:
1 | g++ file1.cpp file2.cpp -o output |
输出结果:
1 | Accessing g_Int in file2.cpp: 42 |
注意:
extern
只是声明变量或函数,并不分配内存或生成代码。定义(即分配内存或生成代码的操作)必须在某个编译单元中完成。- 如果在多个编译单元中定义同一全局变量而没有使用
extern
,会导致链接错误。
extern "C"
用于 C++ 和 C 的混合编程
C++ 支持函数重载,这意味着同名的函数可以根据参数类型不同而有不同的实现。为了实现这一特性,C++ 会对函数进行“名称修饰(name mangling)”,即改变函数的符号名(通常包含有关函数参数类型的信息)。这使得同名函数能够在符号表中共存。
而 C 语言不支持函数重载,因此 C 函数的符号名保持不变。为了让 C++ 和 C 代码能够互相调用,C++ 提供了 extern "C"
关键字,指示编译器在处理某些函数时,按照 C 的命名规则来处理,而不是进行 C++ 的名称修饰。
例子:
- C 代码:
c_code.c
1 |
|
- C++ 代码:
cpp_code.cpp
1 |
|
编译和链接:
1 | g++ cpp_code.cpp c_code.c -o mixed_output |
1 | Calling C function from C++: |
解释:
- 在
cpp_code.cpp
中,extern "C"
告诉编译器不要对c_function
进行名称修饰,而是按 C 的方式保留符号名。 - 这使得 C++ 可以调用用 C 编译的函数
c_function
,并在链接时正常找到它。
3. extern
与 const
的结合
在 C++ 中,const
全局变量的默认作用域是内部链接(类似于 static
),这意味着它只能在定义它的编译单元中使用。如果想要在多个编译单元中共享 const
全局变量,可以使用 extern
修饰。
例子:
- 文件1:
const_file1.cpp
1 |
|
- 文件2:
const_file2.cpp
1 |
|
编译和链接:
1 | g++ const_file1.cpp const_file2.cpp -o const_output |
输出结果:
1 | Accessing g_ConstInt in const_file2.cpp: 100 |
解释:
g_ConstInt
是一个const
全局变量,默认只能在定义它的编译单元中访问。- 通过在
const_file2.cpp
中使用extern
声明g_ConstInt
,使得我们可以在另一个编译单元中访问这个const
变量。
extern
与static
的对比
extern
:声明变量或函数在其他编译单元中定义,并告知编译器在链接时解决符号。static
:限制变量或函数的作用域为当前编译单元,不能在其他编译单元中访问。
例子:
- 文件1:
static_file1.cpp
1 |
|
- 文件2:
static_file2.cpp
1 |
|
编译和链接:
1 | g++ static_file1.cpp static_file2.cpp -o static_output |
输出结果:
1 | g_StaticInt in static_file1.cpp: 10 |
解释:
g_StaticInt
是一个static
全局变量,因此它的作用域仅限于static_file1.cpp
。尝试在static_file2.cpp
中通过extern
声明它会导致链接错误。- 不过,
static_file2.cpp
仍然可以通过调用file1.cpp
中公开的函数printStaticInt
来间接访问g_StaticInt
。
总结
extern
是一个声明关键字,用于告诉编译器某个变量或函数的定义在其他编译单元中。extern "C"
用于在 C++ 中与 C 语言进行链接兼容,防止名称修饰。extern
与const
可以结合使用,通过extern
声明const
全局变量,使其在多个编译单元中共享。extern
与static
是两个相对的关键字:extern
用于声明外部链接,static
用于限制内部链接。
评论