extern关键字总结
【本文链接】
http://www.cnblogs.com/hellogiser/p/extern.html
【extern 变量/函数】
extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,有2种方式:
(1)extern告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数。
(2)extern说明变量或者函数声明在其他的源文件里,而不用include头文件的方式来引用该函数时,链接器在各个模块中搜索这个变量或者函数来进行最终链接。
与extern对应的关键字是 static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。
【extern_include方案】
extern 变量和函数的声明必须在B.h文件中,其定义必须在B.cpp文件中;在A.cpp中引用的时候要include "b.h"
例如MyClass.h
1
2 3 4 5 |
#pragma once
// method 1 |
MyClass.cpp
1
2 3 4 5 6 7 8 9 |
#include "StdAfx.h"
#include "MyClass.h" // method 1 definition |
如何在main.cpp中使用?
main.cpp
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include "stdafx.h"
#include <iostream> #include "MyClass.h" // extern int myA; extern int myAdd(int,int) using namespace std; void test_extern_include() void test_main() int main() |
【extern方案】
MyClass.h
extern 变量必须定义在B.h文件中,extern函数通常定义在B.cpp文件中,也可以定义在B.h文件中。在A.cpp中引用的时候要不能够添加include "b.h",但是要添加extern变量和函数声明。
MyClass.h
1
2 3 4 5 |
#pragma once
// method 2 |
MyClass.cpp
1
2 3 4 5 6 7 8 |
#include "StdAfx.h"
#include "MyClass.h" // method 2 definition |
main.cpp
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#include "stdafx.h"
#include <iostream> //#include "MyClass.h" // extern int myA; extern int myAdd(int,int) using namespace std; extern int myB; void test_extern() void test_main() int main() |
【extern 变量】
在一个源文件里定义了一个数组:char a[6];
在另外一个文件里用下列语句进行了声明:extern char *a;
请问,这样可以吗?
答案与分析:
不可以,程序运行时会告诉你非法访问。原因在于,指向类型T的指针并不等价于类型T的数组。extern char *a声明的是一个指针变量而不是字符数组,因此与实际的定义不同,从而造成运行时非法访问。应该将声明改为extern char a[ ]。
【extern 函数】
当函数提供方单方面修改函数原型时,如果使用方不知情继续沿用原来的extern申明,这样编译时编译器不会报错。但是在运行过程中,因为少了或者多了输入参数,往往会照成系统错误,这种情况应该如何解决?
答案与分析:
目前业界针对这种情况的处理没有一个很完美的方案,通常的做法是提供方在自己的xxx_pub.h中提供对外部接口的声明,然后调用方include该头文件,从而省去extern这一步。以避免这种错误。
【extern “C”】
在C++环境下使用C函数的时候,常常会出现编译器无法找到obj模块中的C函数定义,从而导致链接失败的情况,应该如何解决这种情况呢?
答案与分析:
C++语言在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而C语言则不会,因此会造成链接时找不到对应函数的情况,此时C函数就需要用extern “C”进行链接指定,这告诉编译器,这是一个用C写成的函数,请用C的方式来链接它们,不要生成用于链接的中间函数名。
带extern “C”的代码在处理函数名称时,直接使用函数的名称,不采用特别的方法生成一个中间函数名称;
而没有带extern ”C”的代码在处理函数名称时,使用特别方法生成一个中间函数名称。所以C++函数在使用C函数时,加上extern “C”才能正确的找到指定的函数。
【解决方案】
1.如果函数库没有考虑C++引用的情况,已生成库文件。我们在使用它的头文件时,可以如此使用可解决连接问题,这样时候后编译在引用cgi.h中的函数时,会按照C语言方式引用:
1
2 3 |
extern "C" {
#include "cgi.h" } |
2.如果要写一个C函数库,我们应当尽量采用如下书写方式,而避免C++用户出现1中的问题。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// at the start of cgi.h
#ifdef __cplusplus extern "C" { #endif /* __cplusplus */ //============================ |
extern关键字总结的更多相关文章
- 16-static和extern关键字2-对变量的作用
上一讲介绍了static和extern对函数的作用,static用来定义一个内部函数,不允许其他文件访问:extern用来定义和声明一个外部函数,允许其他文件访问.static和extern对变量也有 ...
- 15-static和extern关键字1-对函数的作用
一.extern与函数 如果一个程序中有多个源文件(.c),编译成功会生成对应的多个目标文件(.obj),这些目标文件还不能单独运行,因为这些目标文件之间可能会有关联,比如a.obj可能会调用c.ob ...
- 【转载】C/C++中extern关键字详解
1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...
- C++中extern关键字用法小结
总结C++中关于extern关键字的用法. 1.变量的生明和定义中 C++语言支持分离式编译机制,该机制允许将程序分割为若干个文件,每个文件可被独立编译.为了将程序分为许多文件,则需要在文件中共享代码 ...
- 解决全局变量共享---C语言的extern关键字用法
在调试程序时,有一个参数需要在多个函数之间传递,因为是作为调试参数,不想将参数引入到函数中. 很自然的想到使用全局变量来表示这个公共参数,工程代码的结构如下: main.c test.c test.h ...
- C语言中的 extern 关键字
今天在 BLE 中看到很多 extern 关键字,现在总结一下: extern 关键字主要用于在一个c文件中要用到另一个c文件中的变量或者函数. example: #extern_base.c ; # ...
- 转载 浅谈C/C++中的static和extern关键字
浅谈C/C++中的static和extern关键字 2011-04-21 16:57 海子 博客园 字号:T | T static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.ext ...
- 浅谈C/C++中的static和extern关键字 转
原文:http://developer.51cto.com/art/201104/256820.htm static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.extern, &quo ...
- 关于全局变量和函数,在其他类中调用问题,extern关键字
1个工程下有几个类文件,和1个全局的文件comm.h, comm.h中存放了这几个类同时需要的变量和同时调用的函数. 当时,我只在comm.h中定义: int commData1: vector&l ...
- C语言的static和extern关键字
我的博客:www.while0.com 如果A.c要包含B.c里的一个变量或函数,则在A.c中要用extern关键字声明.注意: ①如果是包含的B.c里的函数,则在A.c里声明的时候可以不写exter ...
随机推荐
- iOS边练边学--NSURLConnection发送HTTP请求以及NSString和NSData的相互转换
HTTP请求的常见方法 GET 所有参数拼接在URL后面,并且参数之间用&隔开 比如http://520it.com?name=123&pwd=345 传递了2个参数给服务器 name ...
- 使用TransactionScopeOption 管理事务流
可通过调用一个方法来嵌套事务范围,该方法在使用其自己范围的方法中使用 TransactionScope,下面示例中的 RootMethod 方法就是前者这样的方法. void RootMethod() ...
- requirejs
//index.html <!doctype html> <html> <head> <meta charset="utf-8"> ...
- 利用HTML5的Video进行视频截图并保存到本地
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- 【HDU 1228】A + B
题 Description 读入两个小于100的正整数A和B,计算A+B. 需要注意的是:A和B的每一位数字由对应的英文单词给出. Input 测试输入包含若干测试用例,每个测试用例占一行,格式 ...
- codeforces 359D 二分答案+RMQ
上学期刷过裸的RMQ模板题,不过那时候一直不理解>_< 其实RMQ很简单: 设f[i][j]表示从i开始的,长度为2^j的一段元素中的最小值or最大值 那么f[i][j]=min/max{ ...
- Java_观察者模式(Observable和Observer)
http://blog.csdn.net/tianjf0514/article/details/7475164/ 一.观察者模式介绍 在Java中通过Observable类和Observer接口实现了 ...
- eclipse中Preferences的一些设置
1.在Eclipse里面设置了java文件保存时自动格式化,在java->Code Style->Formatter里设置了自定义的格式化的样式,这样每次保存后都会自动格式化代码,用了一段 ...
- configure: error: Please reinstall the libcurl distribution
configure: error: Please reinstall the libcurl distribution - easy.h should be in /include/curl/ 基本上 ...
- css3应用之自定义选中文字的背景颜色
在看很多的博客主题时候发现大多数都对选中文字的背景颜色做了相应的处理.其实这样是很符合用户体验的.因为有很多的人会用鼠标选择着一行一行的阅读.其中就包括本人... 浏览器中默认的选中的文字颜色为白色, ...