[转]extern用法详解

Posted on 2011-08-16 11:15 单鱼游弋 阅读(98) 评论(0)编辑收藏

1 基本解释
  extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。
  另外,extern也可用来进行链接指定。

2 问题:extern 变量
  在一个源文件里定义了一个数组:char a[6];
  在另外一个文件里用下列语句进行了声明:extern char *a;
  请问,这样可以吗?
  答案与分析:
  1)、不可以,程序运行时会告诉你非法访问。原因在于,指向类型T的指针并不等价于类型T的数组。extern char *a声明的是一个指针变量而不是字符数组,因此与实际的定义不同,从而造成运行时非法访问。应该将声明改为extern char a[ ]。
  2)、例子分析如下,如果a[] = "abcd",则外部变量a=0x61626364 (abcd的ASCII码值),*a显然没有意义
  显然a指向的空间(0x61626364)没有意义,易出现非法内存访问。
  3)、这提示我们,在使用extern时候要严格对应声明时的格式,在实际编程中,这样的错误屡见不鲜。
  4)、extern用在变量声明中常常有这样一个作用,你在*.c文件中声明了一个全局的变量,这个全局的变量如果要被引用,就放在*.h中并用extern来声明。

4 问题:extern 函数2
  当函数提供方单方面修改函数原型时,如果使用方不知情继续沿用原来的extern申明,这样编译时编译器不会报错。但是在运行过程中,因为少了或者多了输入参数,往往会照成系统错误,这种情况应该如何解决?
  答案与分析:
  目前业界针对这种情况的处理没有一个很完美的方案,通常的做法是提供方在自己的xxx_pub.h中提供对外部接口的声明,然后调用方include该头文件,从而省去extern这一步。以避免这种错误。
  宝剑有双锋,对extern的应用,不同的场合应该选择不同的做法。

5 问题:extern “C”
  在C++环境下使用C函数的时候,常常会出现编译器无法找到obj模块中的C函数定义,从而导致链接失败的情况,应该如何解决这种情况呢?

  答案与分析:
  C++语言在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而C语言则不会,因此会造成链接时找不到对应函数的情况,此时C函数就需要用extern “C”进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间函数名。
  下面是一个标准的写法:
//在.h文件的头上
#ifdef __cplusplus
#if __cplusplus
extern "C"{
 #endif
 #endif /* __cplusplus */
 …
 …
 //.h文件结束的地方
 #ifdef __cplusplus
 #if __cplusplus
}
#endif
#endif /* __cplusplus */

3 问题:extern 函数1
  常常见extern放在函数的前面成为函数声明的一部分,那么,C语言的关键字extern在函数的声明中起什么作用?
  答案与分析:
  如果函数的声明中带有关键字extern,仅仅是暗示这个函数可能在别的源文件里定义,没有其它作用。即下述两个函数声明没有明显的区别:
extern int f(); 和int f();
  当然,这样的用处还是有的,就是在程序中取代include “*.h”来声明函数,在一些复杂的项目中,我比较习惯在所有的函数声明前添加extern修饰。

=================================================================================================================================

用例子给你示范
// 1.cpp
int x = 10;
// 2.cpp 注意没有包含1.cpp
#include <iostream>
using namespace std;
extern int x;
int main ()
{ cout << x << endl; }
//则输出10
两个文件同在一个项目(project)中,你不包含某个文件(cpp)而可以用它内部定义的变量,(里是.pp不是.h, 因为在.h中定义的数据不能在.cpp中用除非这个.cpp包含这个.h文件)
例:
// 1.h
#include <iostream>
void print()
{
std::cout << "hello!" << std::endl;
}
// 2.cpp
#include <iostream>
using namespace std;
// 以上两句在这个例子中可以不要
extern void print();
int main ()
{
print();
}
就会出错因为1.h中的void print();在不包含它的文件中是不可调用的,即使在声明了extern 也于事无补,如果你将这个例子中的1.h名字换成1.cpp就对了!
从这些可以看出来,extern在这里起的作用是告诉编译器,你这个print()已经在某个.cpp中已经定义了,这里只不过是声明一下有这个东西,然后拿来用一下。定义只能出现一次,声明却可出现多次,也就是说extern声明可在多个文件中用(包括.h)
还有,你还可以屏蔽extern声明,如第二个例子中的第二个.cpp文件可以改成
#include <iostream>
using namespace std;
// 这里以上两句不能省略,因为,这里extern void print();函数已经不起作用了,在这里调用的而是本文件中定义的void print()函数,其中用到了cout,endl;他们来源于std::<iostream>
extern void print();
void print()
{
cout << "world!" << endl;
} int main ()
{
print();
}
// 输出结果为world!
还有一个extern "C"就不用说了,用这个可以允许C++程序中调用C的函数!
==================================================================================================================================
<p style="color: rgb(54, 46, 43); font-family: Arial; font-size: 14px; line-height: 26px;">extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。</p><p style="color: rgb(54, 46, 43); font-family: Arial; font-size: 14px; line-height: 26px;">加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的</p><p style="color: rgb(54, 46, 43); font-family: Arial; font-size: 14px; line-height: 26px;">由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般之包括函数名</p>

extern用法详解相关推荐

  1. extern用法详解(转)

    extern用法详解(转)       1 基本解释 extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义. 另外,extern ...

  2. extern 用法详解

    在C语言中,修饰符extern用在变量或者函数的声明前,用来说明"此变量/函数是在别处定义的,要在此处引用".(extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文 ...

  3. C语言中extern用法详解

    在C语言中,修饰符extern用在变量或者函数的声明前,用来说明"此变量/函数是在别处定义的,要在此处引用".  1. extern修饰变量的声明. 举例来说,如果文件a.c需要引 ...

  4. c语言extern的作用6,C语言中extern用法详解

    本文基于VC6.0 编译器 首先文档结构如下: myextern.h和myextern.c中定义extern函数 main.c中定义main方法,调用extern函数 1.第一个尝试: myexter ...

  5. android搜索功能xml,Android_Android ActionBar搜索功能用法详解,本文实例讲述了Android ActionBar - phpStudy...

    Android ActionBar搜索功能用法详解 本文实例讲述了Android ActionBar搜索功能用法.分享给大家供大家参考,具体如下: 使用ActionBar SearchView时的注意 ...

  6. 【转】__declspec用法详解

    __declspec用法详解 __declspec用于指定所给定类型的实例的与Microsoft相关的存储方式.其它的有关存储方式的修饰符如static与extern等是C和 C++语言的ANSI规范 ...

  7. STL中map和string, vector 用法详解

    1. map 用法详解 std map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成 ...

  8. 转: std::string用法详解

    原文地址为: 转: std::string用法详解  C++中的string 类 简单介绍 前言: string 的角色 1 string 使用 1.1 充分使用string 操作符 1.2 眼花缭乱 ...

  9. #ifdef,#else,#endif,#if用法详解(转)

    #ifdef,#else,#endif,#if用法详解(转) 2011-04-22 10:11 预处理就是在进行编译的第一遍词法扫描和语法分析之前所作的工作.说白了,就是对源文件进行编译前,先对预处理 ...

最新文章

  1. iphone 使用委托(delegate)在不同的窗口之间传递数据
  2. 卸载注册表_系统小技巧:软件卸载不了?这里办法多
  3. SmartSql For Asp.Net Core 最佳实践
  4. 物联网初步之电阻性电路分析 第三部分 电路分析方法和电路原理
  5. 计算机视觉基础:图像处理Task01-图像插值算法
  6. 【转】fatal error C1010: unexpected end of file解决方案
  7. 单机rust怎么设置白天_安卓单机游戏评测:侠盗猎车手3十周年版本
  8. 电磁波中的波段划分:L波段、S波段、C波段、X波段、Ku波段、K波段、Ka波段
  9. 北斗GNSS无人巡检车辆的高精度定位定向应用方案
  10. 输出UTC时间和北京时间
  11. android开源库合集
  12. Flink 第8.2章 Flink 的键组 KeyGroup 与 缩放 Rescale
  13. 对话框不响应WM_KEYDOWN消息,可以通过重载BOOL PreTranslateMessage(MSG * pMsg)来实现
  14. 子网划分以及网络号的计算
  15. 襄阳教育云平台实名认证_襄阳教育云平台登录入口下载|襄阳教育云平台手机版登录入口 V3.8.7-清风安卓软件网...
  16. 【C语言程序】已知一个长方体的高,通过输入长方体的长和宽,计算出长方体的体积
  17. 【数论】ACM数论基础知识总结
  18. Linux常用命令——ss命令
  19. 复制黏贴直接上传图片
  20. Object::connect: No such slot 问题解决办法

热门文章

  1. 什么是RESTful
  2. oracle11g同步,Oracle11g三种数据同步方式-Oracle
  3. java 计算小费_java-以某些形状显示数字
  4. 流式套接字(SOCK_STREAM),数据报套接字 (SOCK_DGRAM) 的比较
  5. 使用ping命令查看网络延迟--用Enki学Linux系列(7)
  6. typedef和函数指针定义
  7. 合法练习黑客技术?这15个网站也许可以帮到你
  8. Ubuntu Linux 永山(mount)分
  9. 关于getCurrentUrl的获取问题
  10. json_decode