static和extern的关系

时间:2021-08-01 16:00:53

static:

  1. 在c语言中,static可以修饰全局变量,局部变量和函数。
    在c++中static修饰类的成员函数,那么这个函数属于这个类,而不是属于这个类的特定对象,static成员函数没有this指针。static修饰类中的变量,表示该变量是该类所有对象共享的,而且这个变量在储存空间中只有一个副本,静态成员函数只能访问静态成员函数和静态成员变量,不能访问非静态的。

    2.1. 修饰局部变量
    一般的局部变量是在栈中存放的,随着函数的生命周期结束而结束。
    但是如果用static进行修饰的话,该变量便存放在静态数据区,其生命周期一直持续到整个程序执行结束。但是在这里要注意的是,虽然用static对局部变量进行修饰过后,其生命周期以及存储空间发生了变化,但是其作用域并没有改变,其仍然是一个局部变量,作用域仅限于该语句块。

#include <iostream>
using namespace std;

void FunTest()
{
static int i = 0;
int j = 0;
++i;
++j;
cout<<"i = "<<i<<" ";
cout<<"j = "<<j<<endl;

}

int main()
{
FunTest();
FunTest();
FunTest();
return 0;
}

static和extern的关系
i是静态局部变量,没有在栈上,虽然出了函数但生命周期没有结束。所以再调用时i从2自增。j是局部变量,随着函数结束就被销毁了,再次调用时重新初始化。 static虽然可以改变变量的生命周期却不能改变作用域。

1.2. static 修饰全局变量
test1.cpp中

int a = 1;

test2.cpp

#include <iostream>
using namespace std;

extern int i ;
int main()
{

cout<<i<<endl;
return 0;
}

则执行结果为 1

但是如果在file1.c中把int a=1改为static int a=1;那么在file2.c是无法访问到变量a的。原因在于用static对全局变量进行修饰改变了其作用域的范围,由原来的整个工程可见变为本源文件可见。

1.3修饰函数
修饰函数的结果和修饰全局变量一样,改变函数的作用域。
在文件域中声明函数为inline函数默认为static。

extern:
在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。
在上面的例子中可以看出,在file2中如果想调用file1中的变量a,只须用extern进行声明即可调用a,这就是extern的作用。在这里要注意extern声明的位置对其作用域也有关系,如果是在main函数中进行声明的,则只能在main函数中调用,在其它函数中不能调用。其实要调用其它文件中的函数和变量,只需把该文件用#include包含进来即可,为啥要用extern?因为用extern会加速程序的编译过程,这样能节省时间。

在C++中extern还有另外一种作用,用于指示C或者C++函数的调用规范。比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原因是C++和C程序编译完成后在目标代码中命名规则不同,用此来解决名字匹配的问题.
对于extern变量来说,仅仅是一个变量的声明,其并不是定义,不会分配内存空间。

内存基本构成

可编程内存在基本上分为这样的几大部分:静态存储区、堆区和栈区。他们的功能不同,对他们使用方式也就不同。

2.1. 静态存储区

内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。

2.2. 栈区

:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

2.3. 堆区

:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。

2.4.代码区:存放函数体的二进制代码。

2.5.文字常量区

在文件作用域声明inline函数默认为static存储类型,const常量默认为static存储,如果加上extern,则为外部存储类型。

extern “C”:
主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern “C”后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般之包括函数名。

 这个功能十分有用处,因为在C++出现以前,很多代码都是C语言写的,而且很底层的库也是C语言写的,为了更好的支持原来的C代码和已经写好的C语言库,需要在C++中尽可能的支持C,而extern "C"就是其中的一个策略。

这个功能主要用在下面的情况:

1、C++代码调用C语言代码

2、在C++的头文件中使用

3、在多个人协同开发时,可能有的人比较擅长C语言,而有的人擅长C++,这样的情况下也会有用到