0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C/C++语言中extern的用法

单片机与嵌入式 来源:单片机与嵌入式 2023-11-29 14:34 次阅读

声明外部变量

现代编译器一般采用按文件编译的方式,因此在编译时,各个文件中定义的全局变量是互相透明的,也就是说,在编译时,全局变量的可见域限制在文件内部。下面举一个简单的例子。创建一个工程,里面含有A.cpp和B.cpp两个简单的C++源文件:

//A.cpp
inti;
voidmain()
{
}
//B.cpp
int i;

这两个文件极为简单,在A.cpp中定义了一个全局变量i,在B中也定义了一个全局变量i。对A和B分别编译,都可以正常通过编译,但是进行链接的时候,却出现了错误,错误提示如下:

Linking...
B.obj:errorLNK2005:"inti"(?i@@3HA)alreadydefinedinA.obj
Debug/A.exe:fatalerrorLNK1169:oneormoremultiplydefinedsymbolsfound
Errorexecutinglink.exe.
A.exe - 2 error(s), 0 warning(s)

这就是说,在编译阶段,各个文件中定义的全局变量相互是透明的,编译A时觉察不到B中也定义了i,同样,编译B时觉察不到A中也定义了i。但是在链接阶段,要将各个文件的内容“合为一体”,因此,如果某些文件中定义的全局变量名相同的话,在链接阶段就会报重复定义(oneormoremultiplydefinedsymbols)的错误。

因此,各个文件中定义的全局变量名不可相同。

在链接阶段,编译产生的obj文件合并了A、B两文件的内容,这也是出现int i重复定义错误的原因。

举个例子

一个文件中定义的全局变量,可以在整个程序的任何地方被使用,举例说,如果A文件中定义了某全局变量,那么B文件中也可以使用该变量。修改我们的程序,加以验证:

//A.cpp
voidmain()
{
i=100; //试图使用B中定义的全局变量
}
//B.cpp
int i;

出现如下意料之中的编译错误,未定义int i错误(undeclaredidentifierError),因为在链接之前A、B文件中的变量是彼此不可见的。

Compiling...
A.cpp 
C:/Documents and Settings/wangjian/桌面/try extern/A.cpp(5) : error C2065: 'i' : undeclared identifier
Errorexecutingcl.exe.
A.obj-1error(s),0warning(s)

编译器没有能够意识到,某个变量符号虽然不是本文件定义的,但是它可能是在其它的文件中定义的,为了避免错误的发生extern派上用场了。为上面的错误程序加上extern关键字后,顺利通过编译,链接,代码如下:

//A.cpp
externinti;
voidmain()
{
i=100;//试图使用B中定义的全局变量
}
//B.cpp
int i;

在C++文件中调用C方式编译的函数

相对于C,C++中新增了诸如重载等新特性,它们的编译有一些重要区别。将下面的小程序分别按C和C++方式编译,来探讨两种编译方式的区别。

inti;
intfunc(intt)
{
  return0;
}
voidmain()
{
}

以C方式编译的结果如下:

COMM_i:DWORD
PUBLIC_func
PUBLIC    _main

以C++方式编译的结果如下:

PUBLIC?i@@3HA;i
PUBLIC?func@@YAHH@Z;func
PUBLIC    _main

可见,C方式编译下,变量名和函数名之前被统一加上了一个下划线,而C++编译后的结果却复杂的多,i变成了?i@@ 3HA ,func变成了?func@@YAHH@Z。C++中的这种看似复杂的命名规则是为C++中的函数重载,参数检查等特性服务的。

不同编译方式下的函数调用

如果在工程中,不仅有CPP文件,还有以C方式编译的C文件,函数调用就会有一些微妙之处。有如下CPP文件A.CPP和C文件B.C两个文件。

//A.CPP
voidfunc();
voidmain()
{
  func();
}

//B.C
void func()
{
}

对A.CPP和B.C分别编译,都没有问题,但是链接时出现错误,原因就是C和CPP不同的编译方式产生的冲突。比如在上文中提到,C方式编译下,变量名和函数名之前被统一加上了一个下划线,而C++编译后的结果却复杂的多,i变成了?i@@ 3HA。

Linking...
A.obj:errorLNK2001:unresolvedexternalsymbol"void__cdeclfunc(void)"(?func@@YAXXZ)
Debug/A.exe:fatalerrorLNK1120:1unresolvedexternals
Errorexecutinglink.exe.
A.exe - 2 error(s), 0 warning(s)

此时,可以通过extern关键字,来帮助编译器解决上面提到的问题。对于本例,只需将A.CPP改成如下代码即可:

//A.CPP
extern "C"
{
  void func(); //引入C语言方式编译的函数或变量
}
void main()
{
  func();
}

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 函数
    +关注

    关注

    3

    文章

    4273

    浏览量

    62290
  • C++
    C++
    +关注

    关注

    21

    文章

    2094

    浏览量

    73442
  • 编译器
    +关注

    关注

    1

    文章

    1614

    浏览量

    49002
  • extern
    +关注

    关注

    0

    文章

    7

    浏览量

    2936

原文标题:C/C++语言中extern的用法

文章出处:【微信号:单片机与嵌入式,微信公众号:单片机与嵌入式】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    C语言中枚举的基本概念和常见用法

    C语言中,枚举是一种方便组织和表示一组相关常量的工具。枚举类型有助于提高代码的可读性和可维护性。本文将介绍C语言枚举的基本概念、语法和用法
    发表于 08-17 15:32 1339次阅读

    单片机的C语言中位操作用法

    单片机的C语言中位操作用法
    发表于 08-17 15:04

    C语言中atoi()函数的用法 相关资料分享

    C语言中atoi()函数的用法
    发表于 07-01 08:12

    C语言中的数据类型有哪几种?const有哪些用法

    C语言中的数据类型有哪几种?const有哪些用法?作用域与static用法是什么?extern是如何去使用的?
    发表于 07-22 06:51

    c语言中typedef的用法

    C语言是一门通用计算机编程语言,应用广泛。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环
    发表于 11-09 15:23 9167次阅读

    解析C语言与ARM汇编与的相互调用以及与 C++ 相互调用

    全局变量只能通过地址间接调用,为了访问C++语言中全局变量,首先要通过extern伪指令引入全局变量,然后将其地址装入寄存器中。
    的头像 发表于 01-23 10:29 5896次阅读

    C++语言的基本构成详细资料说明

    C++语言中的数据类型、运算、语句结构、数组、指针、函数是C++程序设计的基础。掌握这些基本内容,对利用C++语言解决一般应用问题是非常必要
    发表于 02-19 14:49 0次下载
    <b class='flag-5'>C++</b><b class='flag-5'>语言</b>的基本构成详细资料说明

    C语言中的#和##的用法

    和conStr的参数,并且宏conStr和toString中均含有#或者##符号,所以A不能被解引用。导致不符合预期的情况出现。 3.2 解决方案 结果: 责任编辑:xj 原文标题:C语言中#和##的用法 文章出处:【微信公众号
    的头像 发表于 12-06 09:34 7.6w次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言中</b>的#和##的<b class='flag-5'>用法</b>

    C语言C++的特点与用法详细说明

    本文档的主要内容详细介绍的是C语言C++的特点与用法详细说明。
    的头像 发表于 12-26 10:58 4338次阅读

    你真的知道C语言extern C有什么作用吗

    externC”又有什么关系呢? 先看下面这个表格,如下所示; 语言 描述 C 函数名可以作为唯一ID和代码段的程序建立联系 C++
    的头像 发表于 08-17 09:35 2435次阅读
    你真的知道<b class='flag-5'>C</b><b class='flag-5'>语言</b>里<b class='flag-5'>extern</b> <b class='flag-5'>C</b>有什么作用吗

    C语言中extern

    在你的C语言代码中,不知能否看到类似下面的代码: 这好像没有什么问题,你应该还会想:“嗯⋯是啊,我们的代码都是这样写的,从来没有因此碰到过什么麻烦啊~”。     你说的没错,如果你的头文件从来没有
    的头像 发表于 11-02 14:35 2415次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言中</b>的<b class='flag-5'>extern</b>

    C语言中的typedef的用法

    在以前的学习中对于C语言中typedef和define的认识是,#define是宏,作用是简单的替换,而typedef也是替换,只不过比define高级的是在替换的时候会进行语法检查。但是后来
    发表于 01-13 13:36 0次下载
    <b class='flag-5'>C</b><b class='flag-5'>语言中</b>的typedef的<b class='flag-5'>用法</b>

    C语言中extern

    这与C++有什么关系呢? 看看__cplusplus(注意前面是两个下划线) 的名字你就应该知道它与C++有很大关系。__cplusplus是一个C++规范规定的预定义宏。你可以信任的是:所有的现代
    的头像 发表于 04-02 16:03 1558次阅读

    详解C语言中特殊用法

    C语言有很多特殊的用法,如果这些特殊用法使用得当,会是你的代码变得更加有健壮,更加容易维护。
    的头像 发表于 07-15 08:57 1393次阅读

    浅析C语言中的regiseter关键字

    C语言中重要的关键字有很多,static const extern我们之前都讲过,还有一个在面试中出现的频率也比较高:register。
    的头像 发表于 08-25 17:10 1061次阅读
    浅析<b class='flag-5'>C</b><b class='flag-5'>语言中</b>的regiseter关键字