C语言与C++中static,extern的用法及区别总结

19 篇文章 3 订阅

在C语言中:

隐藏

  很多人经常会忘了这一条。其实这个作用很常用也很重要。
  当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。
  为理解这句话,我举例来说明。我们要同时编译两个源文件,一个是a.c,另一个是main.c。
  

char a = 'A'; // global variable
void msg() 
{
    printf("Hello\n"); 
}
int main(void)
{    
    extern char a;    
    printf("%c ", a);
    (void)msg();
    return 0;
}

程序的运行结果是:
A Hello

  为什么在a.c中定义的全局变量a和函数msg能在main.c中使用?
  前面说过,所有未加static前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。 
  此例中,a是全局变量,msg是函数,并且都没有加static前缀,因此对于另外的源文件main.c是可见的。
  如果加了static,就会对其它源文件隐藏。
  

static char a = 'A'; // global variable
static void msg() 
{
    printf("Hello\n"); 
}
int main(void)
{      
    printf("%c ", a);
    (void)msg();
    return 0;
}

  上面的程序会输出什么呢?
  答案是:报错,找不到a与msg的定义。
  在a和msg的定义前加上static,main.c就看不到它们了。
  利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。

  static可以用作函数和变量的前缀,对于函数来讲,static的作用仅限于隐藏。
  在上面的例子中,含有一个新的关键字——extern
  下面来讲一下static和extern的区别:

extern

  extern告诉编译器这个变量或函数在其他文档里已被定义了。

  看下面的例子:
  

static int i; //只在a文档中用
int j;    //在工程里用
static void init()         //只在a文档中用
{
}
void callme()          //在工程中用
{
   static int sum;
}


extern int j;     //调用a文档里的
extern void callme();  //调用a文档里的
int main()
{
  ...
}

  上面的全局i变量和init()函数只能用在a.c文档中,全局变量sum的作用域只在callme里。变量j和函数callme()的全局限扩充到整个工程文档。所以能够在下面的b.c中用extern关键字调用。extern告诉编译器这个变量或函数在其他文档里已被定义了。

extern C

  extern的另外用法是当C和C++混合编程时假如c++调用的是c源文档定义的函数或变量,那么要加extern来告诉编译器用c方式命名函数:
  

extern "C"  //在c++文档里调用c文档中的变量
{
   int j;
   void callme();
}
int main()
{
   callme();
}

static法则:

  A、若全局变量仅在单个C文档中访问,则能够将这个变量修改为静态全局变量,以降低模块间的耦合度;
  B、若全局变量仅由单个函数访问,则能够将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;
  C、设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题;

变量

1.变量定义的一般形式

存储类别数据类型变量表;

2.变量定义的作用

①规定了变量的取值范围。
②规定了变量进行的运行操作。
③规定了变量的作用域。
④规定了变量的存储方式。
⑤规定了变量占用的存储空间。

3.局部变量和全局变量

从作用域角度将变量分为局部变量和全局变量。它们采取的存储类别如下:

局部变量:

①自动变量,即动态局部变量(离开函数,值就消失)。
②静态局部变量(离开函数,值仍保留)。
③寄存器变量(离开函数,值就消失)。
④形式参数可以定义为自动变量或寄存器变量。

全局变量:

①静态外部变量(只限本程序文件使用)。
②外部变量(即非静态的外部变量,允许其它程序文件引用)。

动态存储和静态存储

  从变量存在时间可将变量存储分为动态存储和静态存储。
  静态存储是在整个程序运行时都存在,而动态存储则是在调用函数时临时分配存储单元。

动态存储:

①自动变量(函数内有效)。
②寄存器变量(函数内有效)。
③形式参数。

静态存储:

①静态局部变量(函数内有效)。
②静态外部变量(本程序文件内有效)。
③外部变量(整个程序可引用)。

静态存储区和动态存储区

  从变量值存放的位置可将变量存储区分为静态存储区和动态存储区:

内存中静态存储区:

①静态局部变量。
②静态外部变量。
③外部变量(可被同一程序其它文件引用)。

内存中动态存储区:自动变量和形式参数。

CPU中的寄存器:寄存器变量。

全局变量

  全局变量有外部、静态两种存储方式。

外部全局变量

  全局变量一般用外部存储方式存储,用保留字extern加以定义。此时,变量的作用域是构成整个程序的所有程序文件,也就是定义的外部变量可供其它程序文件使用。
  使用这样的全局变量一定要非常慎重,一旦产生错误,将波及整个程序。

静态全局变量

  如果希望全局变量仅限于本程序文件使用,而其它程序文件中不能引用,这时必须将其存储方式定义为静态存储方式,用保留字static加以定义。此时称为静态外部变量。
例如,在文件filel.c中,如果作这样的定义:

static int a:

  则变量a的作用域被缩小至本程序文件filel1.c,文件file2.c中不能引用。
  值得注意的是对全局变量加static,定义为静态存储方式,并不意味着是静态存储;而不加static,是动态存储。
  两种形式的全局变量(外部变量)都是静态存储方式,都是编译时分配存储空间,但作用域不同。使用静态外部变量,有利于隔离错误,有利于模块化程序设计。

全局变量的缺省存储方式是外部存储方式。

  前面章节中的程序没有见到变量的存储类别定义,实际上采用变量的缺省存储方式。对局部变量采用auto方式,对全局变量采用extern方式。这也是至今为止,我们在程序中没有见到auto、extern等的原因。
至此,我们对变量的存储类别及数据类型进行了全面讨论,在此作个小结。

局部静态变量

  在C/C++中, 局部变量按照存储形式可分为三种auto, static, register。其中register不常用到
  下面主要说说auto和static的区别。

  1. 存储空间分配和生存周期不同

auto类型局部变量就是普通的局部变量(不加修饰的局部变量默认为该类型)。该类型局部变量存储在栈上,在动态存储区,生命周期仅限于定义它的函数,函数结束,它就自动释放。static类型局部变量存储在静态存储区,在程序整个运行期间都不释放。两者之间的作用域相同,但生存期不同。
  2. static局部变量在所处模块在初次运行时进行初始化工作,且只操作一次。
  3. 对于局部静态变量,如果不赋初值,编译期会自动赋初值0或空字符,而auto类型的初值是不确定的

  对于C++中的class对象例外,class的对象实例如果不初始化,则会自动调用默认构造函数,不管是否是static类型
  特点: static局部变量的”记忆性”与生存期的”全局性”

外部静态变量/函数

  
  在C语言中 static有了第二种含义:
  用来表示不能被其它文件访问的全局变量和函数。
  但为了限制全局变量/函数的作用域, 函数或变量前加static使得函数成为静态函数。
  但此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件(所以又称内部函 数)。
  注意此时, 对于外部(全局)变量, 不论是否有static限制, 它的存储区域都是在静态存储区,生存期都是全局的. 此时的static只是起作用域限制作用, 限定作用域在本模块(文件)内部.
  使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名。

静态数据成员/成员函数

前两种C和C++都有,这种仅在C++中有,下面作以下介绍:
  C+ +重用了这个关键字,并赋予它与前面不同的第三种含义:
  表示属于一个类而不是属于此类的任何特定对象的变量和函数.

  这是与普通成员函数的最大区别,也是其应用所在。
  比如在对某一个类的对象进行计数时, 计数生成多少个类的实例,就可以用到静态数据成员。
  在这里面, static既不是限定作用域的, 也不是扩展生存期的作用, 而是指示变量/函数在此类中的唯一性. 这也是”属于一个类而不是属于此类的任何特定对象的变量和函数”的含义.。
  因为它是对整个类来说是唯一的,因此不可能属于某一个实例对象的.
  针对静态数据成员而言, 成员函数不管是否是static, 在内存中只有一个副本, 普通成员函数调用时, 需要传入this指针, static成员函数调用时, 没有this指针。
  
  

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值