extern用法总结

在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。


1. extern修饰变量的声明。

如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v。

这里需要注意的是,被引用的变量v的链接属性必须是外链接(external)的,也就是说a.c要引用到v,不只是取决于在a.c中声明extern int v,还取决于变量v本身是能够被引用到的。

这涉及到c语言的另外一个话题--变量的作用域。能够被其他模块以extern修饰符引用到的变量通常是全局变量

还有很重要的一点是,extern int v可以放在a.c中的任何地方,比如你可以在a.c中的函数fun定义的开头处声明extern int v,然后就可以引用到变量v了,只不过这样只能在函数fun作用域中引用v罢了,这还是变量作用域的问题。对于这一点来说,很多人使用的时候都心存顾虑。好像extern声明只能用于文件作用域似的。

2. extern修饰函数声明。

从本质上来讲,变量和函数没有区别。函数名是指向函数二进制块开头处的指针。

如果文件a.c需要引用b.c中的函数,比如在b.c中原型是int fun(int mu),那么就可以在a.c中声明extern int fun(int mu),然后就能使用fun来做任何事情。

就像变量的声明一样,extern int fun(int mu)可以放在a.c中任何地方,而不一定非要放在a.c的文件作用域的范围中。

对其他模块中函数的引用,最常用的方法是包含这些函数声明的头文件。使用extern和包含头文件来引用函数有什么区别呢?extern的引用方式比包含头文件要简洁得多!extern的使用方法是直接了当的,想引用哪个函数就用extern声明哪个函数。

这样做的一个明显的好处是,会加速程序的编译(确切的说是预处理)的过程,节省时间。在大型C程序编译过程中,这种差异是非常明显的。

函数,函数,对于函数也一样,也是定义和声明,定义的时候用extern,说明这个函数是可以被外部引用的,声明的时候用extern说明这是一个声明。 但由于函数的定义和声明是有区别的,定义函数要有函数体,声明函数没有函数体,所以函数定义和声明时都可以将extern省略掉,反正其他文件也是知道这个函数是在其他地方定义的,所以不加extern也行。两者如此不同,所以省略了extern也不会有问题。

比如:

int fun(void)
{
return 0;
}

很好,我们定义了一个全局函数

int fun(void);
我们对它做了个声明,然后后面就可以用了
加不加extern都一样
我们也可以把对fun的声明 放在一个头文件里,最后变成这样

int fun(void);//函数声明,所以省略了extern,完整些是extern int fun(void);

int fun(void)
{
return 0;
}//一个完整的全局函数定义,因为有函数体,extern同样被省略了。
然后,一个客户,一个要使用你的fun的客户,把这个头文件包含进去,ok,一个全局的声明。没有问题。
但是,对应的,如果是这个客户要使用全局变量,那么要extern 某某变量;不然就成了定义了。

对变量而言,变量的声明有两种情况: 一种是需要建立存储空间的,不用加extern;2、另一种是不需要建立存储空间,需要加extern 。如果你想在本源文件中使用另一个源文件的变量,就需要在使用前用extern声明该变量,或者在头文件中用extern声明该变量;

对函数而言,如果你想在本源文件中使用另一个源文件的函数,就需要在使用前用声明该函数,声明函数加不加extern都没关系,所以在头文件中函数可以不用加extern。



3. 此外,extern修饰符可用于指示C或者C++函数的调用规范。

比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。

这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原因是C++和C程序编译完成后在目标代码中命名规则不同。

还可参考:extern关键字,C语言extern关键字用法详解 (biancheng.net)

### C/C++ 中 `extern` 关键字在头文件中的用法 #### 一、基本概念 `extern` 是一种存储类说明符,在 C 和 C++ 编程语言中用于声明外部变量或函数。它的主要作用是指定某个变量或函数是在另一个源文件中定义的,当前文件只需要引用它即可[^4]。 当涉及到多个源文件时,`extern` 可以帮助实现跨文件的数据共享和函数调用。特别是在头文件中使用 `extern`,可以有效地管理全局变量和函数原型声明。 --- #### 二、C 中 `extern` 的典型用法 在 C 程序中,如果需要在一个文件中访问另一个文件中定义的全局变量,则可以通过 `extern` 进行声明。例如: ```c // 文件 b.c int global_var = 10; void set_global_var(int value) { global_var = value; } // 文件 main.c #include <stdio.h> extern int global_var; // 声明 global_var 来自其他文件 extern void set_global_var(int); int main() { printf("Before setting: %d\n", global_var); set_global_var(20); printf("After setting: %d\n", global_var); return 0; } ``` 上述代码展示了如何通过 `extern` 访问定义在不同文件中的全局变量 `global_var`。 对于函数而言,通常不需要显式地加上 `extern`,因为默认情况下函数就是具有外部链接性的。但如果希望明确指出某函数来自其他文件,也可以写成如下形式: ```c extern void some_function(); ``` 这种做法有助于提高代码可读性和一致性[^5]。 --- #### 三、C++ 中 `extern "C"` 的特殊用途 由于 C++ 支持重载机制以及更复杂的命名规则(即所谓的名称修饰),因此即使两个函数的名字相同,它们也可能因参数列表的不同而被编译器视为不同的实体。然而这会导致一个问题——当尝试从纯 C 库中调用这些未经修改名处理过的函数时会失败[^1]。 为了避免这种情况发生,可以在包含 C 风格接口头文件之前加入一段特殊的语法结构来关闭名字装饰功能: ```cpp #ifdef __cplusplus extern "C" { #endif /* 此处放置标准C风格API */ #ifdef __cplusplus } /* 结束 extern "C" */ #endif ``` 这样做的效果就是在 C++ 环境下告诉编译器按照传统的 C 方式去解析接下来的内容而不是应用其自己的扩展逻辑[^2]。 注意这里使用的条件预处理器指令是为了兼容单独作为 .h 文件存在的场景;如果是直接嵌入到 cpp 源码内部则可以直接简化为简单的 `{}`包裹部分[^3]。 --- #### 四、总结与注意事项 - **变量声明**:在头文件中利用 `extern` 定义全局变量仅限于声明而非实际分配内存空间。 - **防止重复定义错误**:确保每个 `.c/.cpp` 文件只负责初始化一次该变量的实际值。 - **混合编程支持**:借助 `extern "C"` 实现 C 和 C++ 组件间的无缝协作^[]. --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值