extern 用法整理
来源:互联网 发布:手机改编歌词软件 编辑:程序博客网 时间:2024/04/25 23:35
刚开通博客,把原来自己写的一个关于extern的用法整理贴出来供大家参考!有些是copy网上的文章,当然也有不少是自己写的啦!
这几天忙着考试,欢迎大家指证,不过这几天在复习,准备无聊的期末考试就暂时不会回了!以后会更正过来!
一、 用于变量前
1. 在一个文件内声明外部变量,主要是使外部变量的作用范围扩大。
示例:
void main()
{
extern a; //引用之前声明外部变量
printf(“%d/n”,a);
}
int a = 9;
2. 在多个文件的程序中声明外部变量,使其他文件中的变量可以在本程序中使用。
File1:
int A = 9;
void main()
{
}
File2:
extern a;//声明a在别个文件中定义
void fun()
{
printf(“%d/n”,a);
}
二、 用于函数前面
如果函数的声明中带有关键字extern,仅仅是暗示这个函数可能在别的源文件里定义,没有其它作用。所以可以替代include “*.h”的作用。究其原因,函数本身是外部的,所以extern仅仅是声明一下而已。
三、 extern“c”的用法
1. 用法原因解析
C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:
void foo( int x, int y );
该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。
看一段程序:
int i;
int func(int i)
{
return 0;
}
void main()
{
}
C语言编译完后func变成_func,main变成_main;C++编译完后func变成了?func@@YAHH@Z。C++中的这种看似复杂的命名规则是为C++中的函数重载,参数检查等特性服务的。
2. 不同编译方式下的函数调用
如果C语言或者C++的函数调用,对于外部的函数通过头文件或者extern声明都可以实现在本文件中的使用,如果是C和C++的混合编程,这个时候extern “c” 则派上用场了。
//A.CPP
void func();
void main()
{
func();
}
//B.C
void func()
{
}
对A,B分别编译都没有问题,但在链接时则会出问题,原因就在于不同的编译方式产生的冲突,对于文件A,是按照C++的方式进行编译的,其中的func()调用被编译成了?func1@@YAXXZ 。如果B文件也是按照C++方式编译的,那么B中的func函数名也会被编译器改成?func1@@YAXXZ,这样的话,就没有任何问题。但是现在对B文件,是按照C方式编译的,B中的func函数名被改成了_func,这样一来,A中的call ?func1@@YAXXZ这个函数调用就没有了着落,因为在链接器看来,B文件中没有名为?func1@@YAXXZ的函数。事实是,我们编程者知道,B文件中有A中调用的func函数的定义,只不过它是按照C方式编译的,故它的名字被改成了_func。因而,我们需要通过某种方式告诉编译器:“B中定义的函数func()经编译后命名成了_func,而不是?func1@@YAXXZ,你必须通过call _func来调用它,而不是call ?func1@@YAXXZ。”简单的说,就是告诉编译器,调用的func()函数是以C方式编译的,fun();语句必须被编译成call _func;而不是call ?func1@@YAXXZ。
所以我们可以通过extern “C”来解决问题。只需要在A前面加上
extern “C”
{
void fun();
}
同样的extern “c”也可以修饰变量。
A.cpp
extern "C"
{
int a;
}
void main()
{
a = 89;
printf("%d",a);
}
B.c
int a = 9;
3. extern “c”深度剖析
这个从一个面试题说起,什么标准头文件都有类似以下的结构?
#ifndef __INCvxWorksh
#define __INCvxWorksh
#ifdef __cplusplus
extern "C" {
#endif
/*...*/
#ifdef __cplusplus
}
#endif
#endif /* __INCvxWorksh */
显然头文件中#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif” 的作用是防止该头文件被重复引用。那么剩下的又是什么?
__cplusplus是C++程序中预先定义的宏只要是C++的编译器,都隐含定义了__cplusplus宏。如果此时C++程序的话,extern “C”{ 就有效,然后是正文中声明的函数,后面的}也会有效。如果是C语言程序的话则extern “C”未被声明,正文相当普通的函数声明。
- extern 用法整理
- [转][整理]extern "C"的用法解析
- extern用法
- extern用法
- extern用法
- extern 用法
- extern用法
- extern用法
- extern 用法
- extern用法
- Extern用法
- extern用法
- extern用法
- extern 用法
- Extern 用法
- extern用法
- extern用法
- extern 用法
- 对立的虚体!
- C#网络编程(基本概念和操作) - Part.1
- c语言经典算法之数小孩
- 动态替换WinCE的原生驱动!
- java学习之面向对象上(2)
- extern 用法整理
- 大话嵌入式CPU的WinCE烧录
- JAVA线程同步
- CSS读书笔记(1)- 选择器
- CSS读书笔记(2)- 布局
- MeanShift代码
- JavaScript核心指南(JavaScript. The Core.)
- Resin配置SSL说明
- TCC7901的WinCE系统的烧录和设置