C++关键字extern的使用

一、定义

extern是一种“外部声明”的关键字,字面意思就是在此处声明某种变量或函数,在外部定义

如果想声明一个变量而非定义它,就在变量名前添加extern关键字,而且不要显式地初始化变量:

/*
	e.g.2 	以下为3个文件
*/
//test.h
int i=6;//声明,并定义变量

//test2.h
extern int i;//只声明变量

//main.cpp
#include "test.h"
#include "test2.h"
int main()
{
	return 0;
}

注意: 变量能且只能被定义一次,但是可以被声明多次。 extern对应的关键字是static,static表明变量或者函数只能在本模块中使用。因此,被static修饰的变量或者函数不可能被extern C修饰。

二、原理

C++语言支持分离式编译机制,该机制允许将程序分割为若干个文件,每个文件可被独立编译。为了将程序分为许多文件,则需要在文件中共享代码,例如一个文件的代码可能需要另一个文件中中定义的变量。

为了支持分离式编译,C++允许将声明和定义分离开来。变量的声明规定了变量的类型和名字,即使一个名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明。定义则负责创建与名字关联的实体,定义还申请存储空间。

三、其他用法——extern "C"

当它与"C"一起连用时,例如:extern “C” void func(int a);这句话就是告诉编译器,在编译 func 函数名时,按着 C 的规则去翻译相应的函数名,而不是 按C++ 的方式。这个功能十分有用处,因为在C++出现以前,很多代码都是C语言写的,而且很底层的库也是C语言写的,为了更好的支持原来的C代码和已经写好的C语言库,需要在C++中尽可能的支持C,而extern "C"就是其中的一个策略。

这个功能主要用在下面的情况:

  1. C++代码调用C语言代码
  2. 在多个人协同开发时,可能有的人比较擅长C语言,而有的人擅长C++,这样的情况下也会有用到

看一个简单的例子:

有moduleA、moduleB两个模块,B调用A中的代码,其中A是用C语言实现的,即modeleA是一个.c文件,而B是利用C++实现的,即cpp文件,下面给出一种实现方法:

//moduleA头文件
#ifndef __MODULE_A_H //对于模块A来说,这个宏是为了防止头文件的重复引用
#define __MODULE_A_H
int fun(int, int);
#endif
 
//moduleA实现文件moduleA.C //模块A的实现部分并没有改变
#include"moduleA"
int fun(int a, int b)
{
   return a+b;
}
 

//moduleB头文件
#ifndef __MODULE_B_H //很明显这一部分也是为了防止重复引用
#define __MODULE_B_H

#include"moduleA.h"


… //其他代码
 

}
#endif

 
//moduleB实现文件 moduleB.cpp //B模块的实现也没有改变,只是头文件的设计变化了
#include"moduleB.h"
int main()
{
  cout<<fun(2,3)<<endl;
}

编译,

 

编译失败了,因为对于.c文件,windows下的编译器会在c语言符号(变量和函数)前加上“_”,即fun函数被编译后的符号为_fun

而在c++的main中,fun被编译为“?fun@@YAHHH@Z”。两个符号不一致,所以就会在链接过程中报错。

我们修改一下,在moduleB中加入extern "C"

#ifndef __MODULE_B_H //很明显这一部分也是为了防止重复引用
#define __MODULE_B_H

	#ifdef __cplusplus //而这一部分就是告诉编译器,如果定义了__cplusplus(即如果是cpp文件, extern "C"{ //因为cpp文件默认定义了该宏),则采用C语言方式进行编译

	extern "C" { //因为cpp文件默认定义了该宏),则采用C语言方式进行编译
	#include"moduleA.h"
	

    #endif


//其他代码


}

#endif

编译成功

四、C和C++编译和链接的区别

具体原理:

    C++支持函数重载,而C是不支持的。拿一个函数原型void one(int i,int j);举个例子。该函数在C编译器编译后在符号库中的名字为:_one,而C++编译器在编译后会产生类似_one_int_int的名字这个名字包含了函数名字、参数数量、参数类型等信息。C++就是通过这种方式实现了函数重载。

    假如这个函数定义在了一个C++文件中,同时在.c文件中调用了这个函数。那么,当C编译器编译到这个函数的时候,会将这个函数名改为_one,而C++编译器会将这个函数的名称改为_one_int_int,也就是在C编译器得到的目标文件中one()函数是由_one,来引用的。而在C++编译器得到的目标文件中one()函数是由_one_int_int来代替的。

    当连接器工作的时候,它不管上层采用了什么样的语言,它只认目标文件中的符号,于是连接器在C文件中发现调用了one函数,但是在目标文件中却找不到_one的符号,因此会显示连接出错。而加上extern "C"后,是为了向编译器指明这段代码按照C语言的方式进行编译,从而解决了这个问题。

  • 不可以将extern "C" 添加在函数内部
  • 如果函数有多个声明,可以都加extern "C", 也可以只出现在第一次声明中,后面的声明会接受第一个链接指示符的规则。
  • 除extern "C", 还有extern "FORTRAN" 等。

参考:

https://www.cnblogs.com/carsonzhu/p/5272271.html

extern “C++”的用法_extern \“c++\”_一只有理想的程序猿的博客-CSDN博客

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
关键字extern在C语言中的作用是用来声明一个变量或函数的存在,但不定义其具体内容。它的作用是告诉编译器该变量或函数在其他文件中定义或实现。在使用extern关键字声明后,可以通过该声明在当前文件中使用其他文件中定义的变量或函数。 举个例子,假设有两个文件main.c和b.c。在b.c文件中定义了一个变量num和一个函数func。在main.c文件中使用extern关键字声明了num变量,然后就可以在main函数中使用该变量。当程序编译时,编译器会在其他文件中查找num的定义。 <<main.c文件代码>> #include <stdio.h> extern int num; int main() { printf("%d", num); // 在main函数中使用extern声明的num变量 return 0; } <<b.c文件代码>> #include <stdio.h> int num = 5; void func() { printf("fun in a.c"); } 在这个例子中,通过在main.c中使用extern关键字声明了num变量,然后在main函数中进行使用,并打印出了num的值。 另外,值得注意的是,extern关键字实质上是一个声明,必须在其他地方进行定义。在使用extern关键字声明变量后,变量的初始化需要在声明处进行,不能再重新赋值。但声明之后就可以使用变量名进行修改了。 举个例子,假设有以下代码片段: extern int num = 4; // 声明并初始化num变量 #include <stdio.h> int main() { extern int num; // 使用extern声明的num变量 num = 1; // 修改num变量的值 printf("%d", num); return 0; } 在这个例子中,使用extern关键字声明并初始化了num变量,然后在main函数中使用该变量,并修改了它的值。最后打印出了修改后的num的值。 总结起来,关键字extern在C语言中的作用是用来声明一个变量或函数的存在,但不定义其具体内容。它的作用是告诉编译器该变量或函数在其他文件中定义或实现。在使用extern关键字声明后,可以在当前文件中使用其他文件中定义的变量或函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值