c语言中extern的作用

99ANYc3cd6
预计阅读时长 15 分钟
位置: 首页 C语言 正文

extern 是 C 语言中一个非常重要的关键字,它的核心作用是声明一个变量或函数,并告诉编译器这个变量或函数的定义存在于其他文件中

你可以把它想象成一个“预告片”或“声明书”,它只告诉编译器“这个东西存在”,但不会为其分配内存空间,真正的定义(分配内存)会在别的地方发生。


extern 的主要作用

extern 主要用于解决在多文件编程中,变量和函数的作用域问题,它有以下几个核心作用:

声明全局变量,实现跨文件访问(最核心、最常用的作用)

在 C 语言项目中,我们通常会将代码分割成多个 .c 文件(源文件)和 .h 文件(头文件),如果一个全局变量在 file1.c 中定义,我们想在 file2.c 中使用它,就需要在 file2.c 中用 extern 声明它。

示例:

global_var.h (头文件,可选,但推荐)

#ifndef GLOBAL_VAR_H
#define GLOBAL_VAR_H
// 声明一个全局变量,告诉其他文件“这个变量存在,但具体定义在别处”
extern int global_count;
#endif // GLOBAL_VAR_H

file1.c (定义全局变量的文件)

#include "global_var.h"
// 这里是 global_count 的真实定义,编译器会为其分配内存空间
int global_count = 0;
void increment() {
    global_count++;
    printf("file1.c: global_count is now %d\n", global_count);
}

file2.c (使用全局变量的文件)

#include <stdio.h>
#include "global_var.h"
// extern 告诉编译器:global_count 已经在别的地方定义过了,
// 我这里只是要用它,请不要为我重新分配内存。
extern int global_count;
void use_global() {
    printf("file2.c: global_count is %d\n", global_count);
    global_count += 10;
}

main.c (主函数文件)

#include <stdio.h>
#include "global_var.h"
extern int global_count; // 同样需要声明才能使用
extern void increment();
extern void use_global();
int main() {
    printf("Initial global_count: %d\n", global_count);
    increment();
    use_global();
    printf("Final global_count: %d\n", global_count);
    return 0;
}

编译与链接:

# 将所有 .c 文件编译成目标文件
gcc -c file1.c -o file1.o
gcc -c file2.c -o file2.o
gcc -c main.c -o main.o
# 将所有目标文件链接成最终的可执行文件
gcc file1.o file2.o main.o -o my_program
# 运行
./my_program

输出:

Initial global_count: 0
file1.c: global_count is now 1
file2.c: global_count is 1
Final global_count: 11

关键点:

  • 定义 vs. 声明
    • 定义int global_count = 0; 这行代码是定义,它告诉编译器:分配内存给 global_count,并初始化它,一个变量/函数在整个程序中只能被定义一次
    • 声明extern int global_count; 这行代码是声明,它告诉编译器:global_count 这个变量/函数存在,其定义在别处,它可以被声明多次。
  • 编译 vs. 链接
    • 编译:编译器处理每个 .c 文件时,看到 extern,就会认为“好的,这个变量我知道了,我会在后面链接的时候找到它的地址”,它不会为 extern 变量分配内存。
    • 链接:链接器将所有 .o 文件组合在一起,当它发现 file2.o 中引用了 global_countfile1.o 中定义了 global_count,它就会把引用和定义连接起来,解决地址问题。

声明函数

函数的声明通常可以省略 extern,因为函数的默认链接属性就是 extern,也就是说,当你写 int my_func(); 时,编译器默认就认为这是一个外部链接的函数,其定义在其他地方。

以下两种写法在功能上是等价的:

// 写法1:省略 extern (更常见)
int my_func();
// 写法2:显式使用 extern
extern int my_func();

尽管如此,在头文件中显式使用 extern 来声明函数,可以保持代码风格的一致性,并明确地表达“这是一个外部函数”的意图。

修改 C++ 中 conststatic 变量的链接属性

在 C++ 中,conststatic 变量的默认链接属性是 internal(内部链接),意味着它们只能在当前文件内访问,如果想在其他文件中使用,必须用 extern 显式声明。

C++ 示例:

header.h

#ifndef HEADER_H
#define HEADER_H
// 在 C++ 中,一个 const 变量默认是 internal link
extern const int MAX_SIZE; // 声明为外部链接
#endif // HEADER_H

source.cpp

#include "header.h"
// 定义这个 const 变量
const int MAX_SIZE = 100;
void some_function() {
    // ...
}

main.cpp

#include <iostream>
#include "header.h"
int main() {
    std::cout << "MAX_SIZE is: " << MAX_SIZE << std::endl;
    return 0;
}

没有 externmain.cpp 将无法看到 MAX_SIZE,在 C 语言中,const 变量的默认链接属性是 extern,所以这个特性在 C 和 C++ 中有区别。


extern 的语法和位置

  • 语法extern 关键字通常放在变量或函数声明的最前面。
    extern int a;
    extern void my_function(int);
  • 位置
    • 函数:通常放在头文件(.h)中。
    • 全局变量:通常放在头文件(.h)中,或者在使用它的 .c 文件的开头进行声明。

总结表格

作用 解释 示例 备注
跨文件访问全局变量 告诉编译器一个全局变量在其他文件中定义,当前文件只需声明即可使用。 extern int g_var; 最核心的用途,一个变量只能定义一次,但可以声明多次。
声明函数 声明一个函数在其他文件中定义。extern 对函数来说是可选的,因为函数默认就是外部链接。 extern int func();int func(); 保持代码风格一致时使用。
修改C++中const/static的链接属性 在C++中,将默认为内部链接的conststatic变量修改为外部链接,以便跨文件访问。 extern const int MAX; 这是C++特有的用法,C语言中const默认为外部链接。

常见误区

  1. extern 不是定义extern 不会分配内存,如果你在头文件中写了 extern int a = 10;,这实际上是错误的(在某些编译器下可能被当作定义,导致“重定义”错误),定义只能出现在 .c 文件中。
  2. 忘记链接:如果你在一个文件中声明了 extern,但忘记在另一个文件中定义它,链接器会报错,提示“unresolved external symbol”(无法解析的外部符号)。

希望这个详细的解释能帮助你完全理解 extern 在 C 语言中的作用!

-- 展开阅读全文 --
头像
织梦栏目链接调用错误怎么办?
« 上一篇 03-24
dede调用文章tag
下一篇 » 03-24

相关文章

取消
微信二维码
支付宝二维码

目录[+]