一、static

static全局变量与普通的全局变量有什么区别:
static全局变量只初使化一次,防止在其他文件单元中被引用;
static局部变量和普通局部变量有什么区别:
static局部变量只被初始化一次,下一次依据上一次结果值;
static函数与普通函数有什么区别:
static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝

1.1、局部静态变量

在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。

  • 内存中的位置:静态存储区
  • 初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)
  • 作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束。

注:当static用来修饰局部变量的时候,它就改变了局部变量的存储位置,从原来的栈中存放改为静态存储区。但是局部静态变量在离开作用域之后,并没有被销毁,而是仍然驻留在内存当中,直到程序结束,只不过我们不能再对他进行访问。
当static用来修饰全局变量的时候,它就改变了全局变量的作用域(在声明他的文件之外是不可见的),但是没有改变它的存放位置,还是在静态存储区中。

1.2、静态函数

在函数的返回类型前加上关键字static,函数就被定义成为静态函数。
函数的定义和声明默认情况下是**extern的,但静态函数只是在声明他的文件当中可见**,不能被其他文件所用

3.1 定义静态函数的好处:

  • 其他文件中可以定义相同名字的函数,不会发生冲突
  • 静态函数不能被其他文件所用。

    1.3 存储说明符

    存储说明符auto,register,extern,static,对应两种存储期:自动存储期和静态存储期。
    autoregister对应自动存储期。具有自动存储期的变量在进入声明该变量的程序块时被建立,它在该程序块活动时存在,退出该程序块时撤销。
    关键字externstatic用来说明具有静态存储期的变量和函数。用static声明的局部变量具有静态存储持续期(static storage duration),或静态范围(static extent)。虽然他的值在函数调用之间保持有效,但是其名字的可视性仍限制在其局部域内。静态局部对象在程序执行到该对象的声明处时被首次初始化。
  1. //(1) test1.h:#ifndef TEST1H#define TEST1H
  2. static char g_str[] = "123456";
  3. void fun1();
  4. #endif
  5. //(2) test1.cpp:
  6. #include "test1.h"
  7. void fun1()
  8. {
  9. cout << g_str << endl;
  10. }
  11. //(3) test2.cpp
  12. #include "test1.h"
  13. void fun2()
  14. {
  15. cout << g_str << endl;
  16. }

以上两个编译单元可以连接成功, 当你打开test1.obj时,你可以在它里面找到字符串”123456”,同时你也可以在test2.obj中找到它们,它们之所以可以连接成功而没有报重复定义的错误是因为虽然它们有相同的内容,但是存储的物理地址并不一样,就像是两个不同变量赋了相同的值一样,而这两个变量分别作用于它们各自的编译单元。但大多数编译器都对代码都有优化功能,以达到生成的目标程序更节省内存,执行效率更高,当编译器在连接各个编译单元的时候它会把相同内容的内存只拷贝一份,比如上面的”123456”(静态区), 位于两个编译单元中的变量都是同样的内容,那么在连接的时候它在内存中就只会存在一份了,但如果你把上面的代码改成下面的样子,这个优化就会被忽略:

二、extern 变量

2.1 作用

它的作用就是声明函数或全局变量的作用范围的关键字,其声明的函数和变量可以在本模块活其他模块中使用,记住它是一个声明不是定义!

  1. extern char g_str[] = "123456"; //表示声明和定义一起使用
  2. extern char g_str[] //表示声明

三、关于extern “C”

C++是一种面向对象的程序设计语言,为了支持函数的重载,C++对全局函数的处理方式与C有明显的不同。为了支持C函数的使用,加了extern “C”关键字。