c++四只文件中争一同用一个全局变量

例子:

头文件:state.h   源文件:state.cpp       

 此外源文件:t1.cpp  t2.cpp 
t3.cpp, 这个自文件都含头文件state.h。

消定义一个全局变量供这么些来源文件被动用:方法如下

1、在 state.h阐明全局变量: extern
inta;

2、在state.cpp中定义该全局变量:int a
=10;

如此这般任何源文件就好采纳该变量啦

 

 

此地用之是“讲明”,不是“定义”!按照C++标准的规定,一个变量阐明必须以满足个别独规范,否则尽管是概念:  
 (1)讲明必须使用extern关键字;(2)不克让变量赋初值    
  extern  int  a;  //声明 

 int  a;   //定义

 int  a  =  0; //定义

 extern  int  a  =0;   //定义

 

 

     头文件被承诺使用extern关键字注脚全局变量(不定义),假假如变量有多单文本用到,可以新建一个cpp,在其间定义,把这个cpp参加工程即可。头文件要不要定义任何变量,这是老业余的所作所为……

    一般在头文件被注脚,用extern,在cpp中定义。
假使当峰文件被定义,如若此腔文件于两个cpp引用,会招致重复定义的链接错误。

    头文件只好表明全局变量(extern),不可定义(不推荐应用)    .cpp里,在极其外层定义即可(int
gi),直接引用

假如当.cpp里应用static定义,则该变量只当当前cpp文件被行之有效,在其它文件中没用
在.h里使用static定义,不会面展开编译(.h文件未编译),只会晤在那么些每个include的cpp文件中涵盖编译,非常给在.cpp里下static定义。

转载:http://www.cnblogs.com/yyxt/p/3891712.html

1 基本解释:extern可以松手变量或者函数前,以标示变量或者函数的定义在此外文件被,指示编译器碰着是变量和函数时当另外模块中追寻这定义。其它extern也可用来拓展链接指定。

      也就是说extern有点儿只意,第一只,当其与”C”一起连用时,如: extern
“C” void fun(int a, int
b);则告诉编译器在编译fun这些函数名时按着C的条条框框去翻译相应的函数名如不是C++的,C++的平整以翻译者函数名时会把fun这一个名字变得面目全非,可能是fun@aBc_int_int#%$也恐怕是其它,那如看编译器的”脾气”了(不同的编译器选取的计不相同),为啥如此做也,因为C++帮忙函数的重载啊,在这里不错过了多之阐发是问题,虽然你生出趣味可以错过网上找,相信您得赢得满足的说!(C++
和 C 接纳的名修饰规则不一)
    第二,当extern不与”C”在合修饰变量或函数时,如在头文件中: extern
int
g_Int; 它的意就是是声称函数或全局变量的来意范围之要害字,其声称的函数和变量能够于本模块活其他模块中应用,记住它们是一个扬言不是概念!也即是说B模块(编译单元)假设援模块(编译单元)A中定义之全局变量或函数时,它使包含A模块的峰文件即可,在编译阶段,模块B尽管搜索不交该函数或变量,但它不会合报错,它会于接连时由模块A生成的靶子代码中找到那么些函数。

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来声明。

3 问题:单方面修改extern 函数原型
  当函数提供方单方面修改函数原型时,假如应用方不知情继续套用原来的extern注脚,那样编译时编译器不晤面报错。不过当运转过程中,因为少了要多了输入参数,往往会照成系统错误,这种情状应当怎样解决?
  答案和析:
  时业界对这种气象的拍卖没有一个不行周密的方案,常常的做法是取供方在和谐的xxx_pub.h中提供针对性标接口的表明(extern),然后调用方include该头文件,从而省去extern这等同步。以避免这种不当。
  宝剑有双锋,对extern的施用,不同之场馆当选不同之做法。

4 问题:extern “C”
  于C++环境下行使C函数的时段,平日会产出编译器不能够找到obj模块中的C函数定义,从而致使链接战败的情事,应该怎么着缓解这种情形吧?

  答案和分析:
  C++语言在编译的时段为掌握决函数的多态问题,会用函数名叫及参数联合起来别一个中级的函数名称,而C语言则不会面,由此会师招致链接时追寻不交对应函数的情事,此时C函数就得用extern
“C”举行链接指定,这告诉编译器,请保持自己的名号,不要为自己转用于链接的中游函数号称。
  上面是一个业内的写法:

图片 1

//在.h文件的头上
#ifdef __cplusplus
#if __cplusplus
extern "C"{
 #endif
 #endif /* __cplusplus */ 
 …
 …
 //.h文件结束的地方
 #ifdef __cplusplus
 #if __cplusplus
}
#endif
#endif /* __cplusplus */ 

图片 2

 

5 问题:extern 函数声称
  平时见extern放在函数的前方成为函数阐明的一模一样有,那么,C语言的根本字extern在函数的宣示遭从啊功用?
  答案和分析:
  假诺函数的声明中蕴藏关键字extern,仅仅是暗示这函数可能当其余源文件里定义,没有此外企图。即下述两单函数阐明没有确定性的分:

extern int f(); 

int f();

  当然,这样的用仍旧片,就是在程序中代表include
“*.h”来声称函数,在局部扑朔迷离的连串遭到,我相比较习惯以具备的函数注解前续加extern修饰。关于这样做的缘故以及利弊可见下边的此事例:“用extern修饰的全局变量”

    (1) 在test1.h中出下列申明:

    #ifndef TEST1H
    #define TEST1H
    extern char g_str[]; // 声明全局变量g_str
    void fun1();
    #endif

    (2) 在test1.cpp中

    #include "test1.h"
        char g_str[] = "123456"; // 定义全局变量g_str
        void fun1() { cout << g_str << endl; }

    (3) 以上是test1模块,
它的编译和连接都得经,即使我们还有test2模块也想使用g_str,只需要在原来文件中援引就足以了

    #include "test1.h"

     void fun2()    { cout << g_str << endl;    }

   
以上test1和test2能够以编译连接通过,如果您感兴趣的语可以用ultraEdit打开test1.obj,你得于里边找到”123456″这些字符串,但是你也未可以以test2.obj里面找到,这是盖g_str是整套工程的全局变量,在内存中只设有同样卖,test2.obj这些编译单元不需重发生同样客了,不然会当连时喻再度定义之似是而非!

顾:借使下到sizeof,阐明数组需要指定大小 extern char g_str[7];
因为test2模块中不过是声称了一个往往组,但实际多老,并不知道。若没有在.h文件被宣称数组大小,会报“非法的sizeof操作数”的荒谬。

  (4)
有些人喜欢把全局变量的扬言与概念在一块儿,这样可预防遗忘了定义,如将点test1.h反吗
   

extern char g_str[] = "123456"; // 这个时候相当于没有extern

   
然后把test1.cpp中的g_str的定义去丢,这么些时节又编译连接test1和test2两单模块时,会报连接错误,这是盖你将全局变量g_str的定义在了腔文件后,test1.cpp是模块包含了test1.h所以定义了同样不行g_str,而test2.cpp也暗含了test1.h所以再同涂鸦定义了g_str,这些时刻连接器在连接test1和test2时意识少只g_str。假使您免要把g_str的概念在test1.h中的话,那么虽然管test2的代码中#include
“test1.h”去掉 换成:

extern char g_str[];  // 没有include “test1.h”
void fun2()   {  cout << g_str << endl;   }

   这一个时编译器就知道g_str是引自于表面的一个编译模块了,不碰面在本模块被再度还定义一个出来,不过本人思量说这样做老大坏,因为若由于不可能以test2.cpp中动用#include
“test1.h”,那么test1.h中宣称的其它函数你也无能为力运用了,除非也用都用extern修饰,这样的话你但是讲明的函数就假诺一如既往好失误,而且头文件之意图就是假设给外部提供接口使用的,所以
请记住, 只以峰文件中做声明,真理总是这样简单。

6. extern 和 static

 (1) extern 注脚该变量在另外地点曾定义了了,在此而运好变量.
 (2) static 代表静态的变量,分配内存的时, 存储于静态区,不存储于栈下面.

    static 效能范围是里连接的涉及,
和extern有点相反.它与对象自我是分手储存的,extern也是分别储存的,不过extern可以叫其它对象用extern
引用,而static
不可以,只允许对象自我用它. 具体差别首先,static与extern是一样针对“水火不容”的武器,也就是说extern和static不克同时修饰一个变量;其次,static修饰的全局变量表明和定义同时拓展,也就是说当您以峰文件被动用static评释了全局变量(类外部)后(假设以峰文件之class内部宣称static变量,那么其定义式通常位于实现(.cpp)文件中,例外的,唯有const
int类型可以in class
初值设定),它吗同时深受定义了;最终,static修饰全局变量的功能域只好是自家的编译单元(内部链接,参见 储存持续性、效能域和链接性),也就是说它的“全局”只针对本编译单元中,其他编译单元则看不到它们,如:
    (1) test1.h:

#ifndef TEST1H
#define TEST1H
static char g_str[] = "123456"; 
void fun1();
#endif

    (2) test1.cpp:

#include "test1.h"
void fun1()  {   cout << g_str << endl;  }

    (3) test2.cpp

#include "test1.h"
void fun2()  {   cout << g_str << endl;  }

    以上两单编译单元可以连接成,
当你打开test1.obj时,你可当其其中找到字符串”123456″,同时您啊得在test2.obj中找到其,它们之所以可连接成使尚未报再定义的左是坐尽管它们有同一的内容,可是存储的大体地址并无雷同,就比如是个别独不等变量赋了千篇一律之值一样,而这有限单变量分别成效被它分其它编译单元。
也许你相比较比真,自己默默的跟调试下面的代码,结果而发现个别单编译单元(test1,test2)的g_str的内存地址相同,于是你生定论static修饰的变量也得以功效被外模块,不过我一旦告您,这是公的编译器在欺诈你,大多数编译器都针对代码都发优化效率,以达成生成的目的程序更节省内存,执行效率还胜,当编译器在接连各样编译单元的下,它会晤将同内容之内存只拷贝一份,比如下面的”123456″,
位于简单个编译单元中的变量都是平等的内容,那么当接连的早晚她当内存中便只是相会满怀于一如既往客了,要是您拿下边的代码改成为上边的指南,你这便得拆过编译器的鬼话:
    (1) test1.cpp:

#include "test1.h"
void fun1()
{
   g_str[0] = ''a'';
   cout << g_str << endl;
}

    (2) test2.cpp

#include "test1.h"
void fun2()  {  cout << g_str << endl;  }

    (3) 

void main()     {
        fun1(); // a23456
        fun2(); // 123456
    }

   
这多少个时你于跟代码时,就会合发现个别独编译单元中之g_str地址并不相同,因为您在同等远在改动了她,所以编译器被粗鲁的过来内存的天然,在内存中在了区区卖拷贝给点儿单模块中之变量使用。正是因static有上述的特性,所以一般定义static全局变量时,都拿它们置身原文件被使非是条文件,这样就非会晤给此外模块造成不必要之音信污染,同样记住是法吧!

7. extern 和const

  
C++中const修饰的全局常量据有和static相同之性状,即其只好功用被依编译模块中,然而const可以跟extern连用来声称该常量可以成效被其他编译模块中,
如extern const char g_str[];
    然后每当原先文件中生成忘了定义:     const char g_str[] = “123456”; 

    所以当const单独使用时它便和static相同,而当与extern一起搭档之上,它的表征就是跟extern的如出一辙了!所以本着const我并未呀可以过多的叙述,我只是怀恋唤起您,const
char* g_str = “123456” 与 const char g_str[] =”123465″是例外的,
后边那些const 修饰的是char
*而不是g_str,它的g_str并无是常量,它吃用作是一个概念了的全局变量(可以为此外编译单元使用),
所以假设您比如说受char*g_str服从const的大局常量的条条框框,最好这么定义const char* const g_str=”123456″.

【转】http://www.cnblogs.com/yc\_sunniwell/archive/2010/07/14/1777431.html

 

/*************************************************************************/

extern 用法,全局变量与峰文件(重复定义) 

用#include
可以分包其他头文件被变量、函数的声明,为啥还要extern关键字,假使自身牵记引用一个全局变量或函数a,我假若直接当自文件中含有#include<xxx.h> (xxx.h包含了a的扬言)不纵好了么,为什么还要用extern呢??这么些问题一贯为是似乎是如不的
困扰着自我不少年了,明日上网狠狠查了转算小有所获了:

头文件

先是说脚文件,其实头文件对总括机而言没什么效率,她只是于预编译时于#include的地方开展一下,没另外意义了,其实头文件重大是于别人看之。

自开了一个试,将头文件的后缀改成xxx.txt,然后在援该头文件之地点用

#include”xxx.txt”

编译,链接都很顺利的仙逝矣,因此可知,头文件就为看代码功用,没其他的用意了!

无论是是C仍然C++,你管你的函数,变量或者结构体,类啥的在你的.c或者.cpp文件里。然后编译成lib,dll,obj,.o等等,然后别人用之下太基本的gcc hisfile.cpp yourfile.o|obj|dll|lib 等等。
可于大家程序员而言,他们怎么亮你的lib,dll…里面究竟有什么东西?要扣押您的腔文件。你的峰文件就是对准用户之表明。函数,参数,各类各种的接口的征。
这就是说既然是印证,那么头文件里放的自然就是有关函数,变量,类的“注解”了。记在,是“阐明”,不是“定义”。
那么,我如果大家清楚表明和概念之区别。所以,最好不要傻嘻嘻的在头文件里定义什么事物。比如全局变量:

#ifndef _XX_头文件.H
#define _XX_头文件.H
int A;
#endif

那就是说,很不好的凡,这里的int A是单全局变量的概念,所以假设这腔文件于反复引用的话,你的A会为再次定义.
露出然语法上错了。只可是有了这个#ifndef的原则编译,所以会管你的条文件只吃引用一赖,可是或许要会岔子,但假诺四只c文件包含这一个腔文件时依旧会师出错的,因为宏名有效限制只限于本c源文件,所以当及时差不四只c文件编译时凡勿会合出错的,但当链接时就是相会报错,说若基本上处定义了和一个变量,

Linking...
incl2.obj : error LNK2005: "int glb" (?glb@@3HA) already defined in incl1.obj
Debug/incl.exe : fatal error LNK1169: one or more multiply defined symbols found

注意!!!

extern

这么些首要字真的于可恶,在阐明的时段,这一个extern居然可以于略去,所以会合让你搞不清楚到底是宣称或定义,下面细分变量和函数两类来说:

(1)变量

更是于变量来说。

extern int a;//声明一个全局变量a
int a; //定义一个全局变量a
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)
{
    return 0;
}

特别好,我们定义了一个大局函数

int fun(void);

大家本着它们做了个阐明,然后前面就是足以用了, 加不加extern都一样.
俺们为得拿对fun的阐明 放在一个匹文件里,最终成为这样

int fun(void);//函数声明,所以省略了extern,完整些是extern int fun(void);
int fun(void)
{
  return 0;
}//一个完整的全局函数定义,因为有函数体,extern同样被省略了。

下一场,一个客户,一个设以你的fun的客户,把此腔文件包含进去,ok,一个大局的宣示。没有问题。
只是,对应的,如假使这客户要利用全局变量,那么一旦extern 某某变量;不然就是成为了定义了。

总结下:

本着变量而言,若是您想在起点文件被运用任何一个源文件之变量,就需要在运用前用extern表明该变量,或者以头文件中用extern注脚该变量;

针对函数而言,假使你想当起点文件中应用此外一个来文件的函数,就用以动前用阐明该变量,表明函数加不加extern都不要紧,所以于头文件中函数可以不用加extern。

C程序采取模块化的编程思想,需合理地拿一个怪特另外软件划分也平雨后春笋功效独立的有合作完成系统的需要,在模块的细分上重大按照功用。模块由头文件及促成文件组成,对头文件以及实现公文之正确性用办法是:
平整1 头文件(.h)中是对于该模块接口的宣示,接口包括拖欠模块提供被此外模块调用的外部函数和外部全局变量,对这些变量和函数都待在.h闽南语件中冠以extern关键字讲明;
规则2 模块内之函数和全局变量需于.c文件开首冠以static关键字讲明;
平整3 永远不要在.h文件被定义变量;
过多程序员对定义变量和讲明变量混淆不清,定义变量和讲明变量的区分在于定义会起内存分配的操作,是汇编阶段的概念;而注解则只是告诉包含该阐明的模块于连等起外模块寻找外部函数和变量。如:
int a = 5;
#include “module1.h”
#include “module1.h”
#include “module1.h”
上述程序的结果是于模块1、2、3吃还定义了整型变量a,a在不同之模块中对承诺不同的地方单元,这显然不合乎编写者的本意。正确的做法是:
extern int a;
#include “module1.h”
int a = 5;
#include “module1.h”
#include “module1.h”  
这么使模块1、2、3操作a的话语,对应之是平片内存单探花。

规则4 一旦要用此外模块定义之变量和函数,直接包含其头文件即可。
多程序员喜欢这样做,当她们而拜访此外模块定义的变量时,他们当本模块文件开端加上这样的语:
extern int externVar; 
委这种做法吧,只要头文件随规则1形成,某模块要看其余模块中定义之全局变量时,只要包含该模块的峰文件即可。

共享变量讲明
就是比如在函数间共享变量的法子相同,变量可以于文书中共享。为了共享函数,要管函数的定义在一个来自文件中,然后于急需调用此函数的其他文件被放置注明。共享变量的章程与此措施很接近。
以前,不需要区分变量的扬言与她的定义。为了声明变量i,写成如下格局:
int i; 
如此这般不但阐明i是int型的变量,而且也对i举办了概念,从而使编译器为i留出了空中。为了阐明没有概念之变量i,需要以变量讲明的启处于停放关键字extern:
extern int i;
extern提醒编译器变量i是于先后中的旁岗位定义的(大多数恐是以不同之源文件中),由此不需要吗i分配空间。
顺手说一样句,extern可以用于所有品种的变量。在屡次组的扬言遭使用extern时,可以忽略数组的长短:
extern int a[];
因这时候编译器不用为数组a分配空间,所以也不怕无待知道数组a的长短了。
以以几独出自文件中共享变量i,首先把变量i的概念放置于一个文书中:
int i;
一旦用针对变量i初阶化,那么好以此放初叶值。在编译这些文件时,编译器将会合呢变量i分配内存空间,而另外文件拿富含变量i的讲明:
extern int i;
通过以每个文件被宣称变量i,使得在这多少个文件中得看/或涂改变量i。可是,由于根本字extern,使得编译器不汇合于历次编译其中某文件时也变量i分配额外的内存空间。
当于文书中共享变量时,会师临与共享函数时相似的挑衅:确保变量的具备宣称与变量的定义一致。
为了制止争辨,日常将共享变量的表明放置于峰文件中。需要看分外变量的源文件可以略晚含有适当的条文件。其它,含有变量定义的源文件包含各级一个蕴含变量讲明的腔文件,这样假若编译器可以检查两者是否匹配。

如果工程雅酷,头文件过多,而有几乎独头文件同时是隔三差五要就此之,那么
1。把这么些头文件全体形容到一个峰文件中去,比如写及preh.h
2。写一个preh.c,里面仅同句子话:#include “preh.h”
3。对于preh.c,在project setting里面安装creat precompiled headers,对于其他c文件,设置use precompiled header file