extern的使用之变量与函数
2012-08-16 11:31
169 查看
extern
谨记:声明可以多次,定义只能一次。这个关键字真的比较可恶,在声明(函数)的时候,这个extern居然可以被省略,所以会让你搞不清楚到底是声明还是定义,下面分变量和函数两类来说:
(1)变量
尤其是对于变量来说。
extern int a;//声明一个全局变量a
int a; //定义一个全局变量a,外部变量如果没有初始化其值为0
extern int a =0 ;//定义一个全局变量a 并给初值。
int a =0;//定义一个全局变量a,并给初值,
声明之后你不能直接使用这个变量,需要定义之后才能使用。
第四个 等于第 三个,都是定义一个可以被外部使用的全局变量,并给初值。
糊涂了吧,他们看上去可真像。但是定义只能出现在一处。也就是说,不管是int a;还是extern int a=0;还是int a=0;都只能出现一次,而那个extern int a可以出现很多次。
当你要引用一个全局变量的时候,你就要声明extern int a;这时候extern不能省略,因为省略了,就变成int a;这是一个定义,不是声明。
(2)函数
对于函数也是定义和声明,定义的时候用extern,说明这个函数是可以被外部引用的,声明的时候用extern说明这是一个声明。 但由于函数的定义和声明是有区别的,定义函数要有函数体,声明函数没有函数体,所以函数定义和声明时都可以将extern省略掉,反正其他文件也是知道这个函数是在其他地方定义的,所以不加extern也行。两者如此不同,所以省略了extern也不会有问题。
比如:
int fun(void)
{
return0;
}
很好,我们定义了一个全局函数
int fun(void);
我们对它做了个声明,然后后面就可以用了
加不加extern都一样
我们也可以把对fun的声明 放在一个头文件里,最后变成这样
int fun(void);//函数声明,所以省略了extern,完整些是extern int fun(void);
intfun(void)
{
return0;
}//一个完整的全局函数定义,因为有函数体,extern同样被省略了。
然后,一个客户,一个要使用你的fun的客户,把这个头文件包含进去,ok,一个全局的声明。没有问题。
但是,对应的,如果是这个客户要使用全局变量,那么要extern 某某变量;不然就成了定义了。
总结下:
对变量而言,变量的声明有两种情况: 一种是需要建立存储空间的不用加extern;2、另一种是不需要建立存储空间需要加extern 。如果你想在本源文件中使用另一个源文件的变量,就需要在使用前用extern声明该变量,或者在头文件中用extern声明该变量;
对函数而言,如果你想在本源文件中使用另一个源文件的函数,就需要在使用前用声明该变量,声明函数加不加extern都没关系,所以在头文件中函数可以不用加extern。
extern "C"的用法
链接指示符extern C如果程序员希望调用其他程序设计语言尤其是C 写的函数,那么调用函数时必须告诉编译器使用不同的要求,例如当这样的函数被调用时函数名或参数排列的顺序可能
不同,无论是C++函数调用它还是用其他语言写的函数调用它,程序员用链接指示符linkage directive 告诉编译器该函数是用其他的程序设计语言编写的,链接指示符有两种形式既可以是单一语句single statement 形式也可以是复合语句compound statement形式。
// 单一语句形式的链接指示符
extern "C" void exit(int);
// 复合语句形式的链接指示符
extern "C" {
int printf( const char* ... );
int scanf( const char* ... );
}
// 复合语句形式的链接指示符
extern "C" {
#include <cmath>
}
链接指示符的第一种形式由关键字extern 后跟一个字符串常量以及一个普通的函数,声明构成虽然函数是用另外一种语言编写的但调用它仍然需要类型检查例如编译器会检查传递给函数exit()的实参的类型是否是int 或者能够隐式地转换成int 型,多个函数声明可以用花括号包含在链接指示符复合语句中,这是链接指示符的第二种形式花扩号被用作分割符表示链接指示符应用在哪些声明上在其他意义上该花括号被忽略,所以在花括号中声明的函数名对外是可见的就好像函数是在复合语句外声明的一样,例如在前面的例子中复合语句extern
"C"表示函数printf()和scanf()是在C 语言中写的,函数因此这个声明的意义就如同printf()和scanf()是在extern"C"复合语句外面声明的一样,当复合语句链接指示符的括号中含有#include 时在头文件中的函数声明都被假定是用链接指示符的程序设计语言所写的在前面的例子中在头文件<cmath>中声明的函数都是C函数链接指示符不能出现在函数体中下列代码段将会导致编译错误。
int main()
{
// 错误: 链接指示符不能出现在函数内
extern "C" double sqrt( double );
double getValue(); //ok
double result = sqrt ( getValue() );
//...
return 0;
}
如果把链接指示符移到函数体外程序编译将无错误
extern "C" double sqrt( double );
int main()
{
double getValue(); //ok
double result = sqrt ( getValue() );
//...
return 0;
}
但是把链接指示符放在头文件中更合适在那里函数声明描述了函数的接口所属,如果我们希望C++函数能够为C 程序所用又该怎么办呢我们也可以使用extern "C"链接指示符来使C++函数为C 程序可用例如。
// 函数calc() 可以被C 程序调用
extern "C" double calc( double dparm ) { /*... */ }
如果一个函数在同一文件中不只被声明一次则链接指示符可以出现在每个声明中它,也可以只出现在函数的第一次声明中在这种情况下第二个及以后的声明都接受第一个声
明中链接指示符指定的链接规则例如
// ---- myMath.h ----
extern "C" double calc( double );
// ---- myMath.C ----
// 在Math.h 中的calc()的声明
#include "myMath.h"
// 定义了extern "C" calc() 函数
// calc() 可以从C 程序中被调用
double calc( double dparm ) { // ...
在本节中我们只看到为C 语言提供的链接指示extern "C",extern "C"是惟一被保证由所有C++实现都支持的,每个编译器实现都可以为其环境下常用的语言提供其他链接指示例如extern "Ada"可以用来声明是用Ada 语言写的函数,extern "FORTRAN"用来声明是用FORTRAN 语言写的函数,等等因为其他的链接指示随着具体实现的不同而不同所以建议读者查看编译器的用户指南以获得其他链接指示符的进一步信息。
总结 extern “C”
extern “C”不但具有传统的声明外部变量的功能,还具有告知C++链接器使用C函数规范来链接的功能。还具有告知C++编译器使用C规范来命名的功能。
相关文章推荐
- static(c中定义的关键字1、被其修饰者 外部无法使用(相反的都可以使用extern在外部使用) 2、函数局部变量使用成为静态的放入静态池-生存期改变。c++进行了扩充,使它在类中有了特殊作用)
- LoadRunner lr_eval_string() 函数使用及LR中变量、参数的简单使用
- C++学习小记(使用定义在其他.cpp文件中的变量或函数)
- MFC在其他类中使用MainFrame中的变量或函数
- 多文件程序(extern声明、内部函数、外部函数、外部变量、文件包含)
- 从零开始学C++之对象的使用(一):static 成员变量、static 成员函数、类/对象的大小
- C语言 extern3 全局变量的使用
- C语言中使用extern修饰函数要注意(转)
- js中函数、变量如何在C#中使用?C#中函数、变量如何在js中使用?
- 在Angular外部使用js调用Angular控制器中提供的函数方法或变量
- extern "C" __stdcall对函数的使用声明
- extern变量定义及使用方式实例
- ajax使用函数中的this变量问题及其解决方法
- javascript使用isNaN()函数判断变量是否为数字
- lr_eval_string()函数以及LR中参数、变量的简单使用
- 使用函数交换两个变量的值
- 在内部类中如果要使用函数中定义的变量的情况
- salesforce 零基础学习(六十六)VF页面应善于使用变量和函数(二)常用函数的使用
- python嵌套函数使用外部函数变量的方法(Python2和Python3)
- yii框架中常用变量、函数使用总结