转载于:https://blog.csdn.net/weixin_42167759/article/details/80287748
*******************************概念********************************************
*******************************************************************************
首先得明白全局变量、静态全局变量、局部变量、静态局部变量的概念,下面进行举例:
-
//main.c文件中
-
int a =
0;
//全局变量
-
static
int b=
0;
//静态全局变量
-
main()
-
{
-
int c;
//局部变量
-
static
int d;
//静态局部变量
-
}
- 全局变量:具有全局作用域,全局变量只需在一个源文件中定义,就可以作用于所有的源文件。
- 静态全局变量:具有全局作用域,它与全局变量的区别在于如果程序包含多个文件的话,它作用于定义它的文件里,不能作用到其它文件里,即被 static 关键字修饰过的变量具有文件作用域。
- 局部变量:具有局部作用域,它是自动对象(auto),它在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用执行结束后,变量被撤销,其所占用的内存也被收回。
- 静态局部变量:具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行结束都一直存在。
**************************C语言中的static的用法********************************
*******************************************************************************
static变量 ( 修饰全局变量 与 局部变量) 的例子:
-
#include<stdio.h>
-
static
int j;
//修饰静态的全局变量
-
int funOne(
void)
-
{
-
static
int i =
0;
//修饰静态的局部变量
-
i++;
-
return i;
-
}
-
-
int funTwo(
void)
-
{
-
j =
0;
-
j=j+
2;
-
return j;
-
}
-
-
int main()
-
{
-
int k =
0,m =
0,n =
0;
-
for(k =
0;k <
5;k++)
-
{
-
m = funOne();
-
n = funTwo();
-
printf(
"m=%d,n=%d\n",m,n);
-
}
-
return
0;
-
}
****************结果显示如下****************
m=1,n=2
m=2,n=2
m=3,n=2
m=4,n=2
m=5,n=2
************对结果的解释说明************
对于funOne( ),运行一次之后,变量i保持了原来的数据,并没有销毁,而是在下一次调用的时候继>续使用,所以才会有1、2、3…5这样的结果。而对于funTwo( ),运行一次之后,变量j的值被销毁了,所>以第二次调用结束j仍然保持原值“1”,所以循环五次,每次都是1
1、static修饰全局变量——静态全局变量
使用方法:在全局变量前面加static关键字,例如:static int i = 0;
初始化:未经初始化的全局变量会被自动初始化为0(自动对象的值是任意的,除非他被显示初始化);
存储的位置:静态存储区 (static) ,全局变量和静态变量是存储在一起的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后由系统自动释放。
变量的作用域:具有全局作用域,只初始化一次,它与全局变量的区别在于如果程序包含多个文件的话,它作用于定义它的文件里,不能作用到其它文件里,即被 static 关键字修饰过的变量具有文件作用域。(使得作用域仅限于被定义的文件中 即,从变量定义到本文件结尾处,其他文件不论通过什么方式都不能访问)。
总结:静态局部变量值初始化一次;若不赋初值,在初始化的时候会自动赋值为0;只作用于定义他的文件中,不能作用于其他的文件中;把全局变量改变为静态变量是改变了他作用域。
2、static修饰局部变量——静态局部变量
使用方法:在局部变量前面加static关键字,例如:static int j;
初始化:未经初始化的局部变量会被自动初始化为0(自动对象的值是任意的,除非他被显示初始化);
存储的位置:静态存储区 (static) ,全局变量和静态变量是存储在一起的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后由系统自动释放。
引入静态局部变量的原因:
通常再函数体内定义了一个变量,每当程序运行到改函数时候就会给局部变量分配栈内存,但随着程序退出函数体,系统就会收回栈内存,局部变量也响应的失效。但是有的时候我们需要在两次调用之间对变量的值进项保存。通常的想法是定义一个全局变量来实现。但是这样一来,变量就已经不再属于函数本身了,不再仅受函数的控制,给程序的维护带来不便利。静态局部变量正好解决了这个问题,静态局部变量保存在全局数据区(静态存储区),而不是保存在栈中,每次的值保持到下一次调用,直到下一次赋新值。
变量的作用域:具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行结束都一直存在。(当定义他的函数或者语句块结束的时候,作用域结束,但是当局部静态变量离开作用域后,并没有被销毁,而是仍然驻留在内存当中,只不过我们不能再对他进行访问,直到改函数再次被调用吗,并且值不变)
总结:静态局部变量值初始化一次;若不赋初值,在初始化的时候会自动赋值为0;只对定义自己的函数体始终可见;把局部变量改变为静态变量是改变了他的存储方式即改变了他的生存周期。
静态局部变量与动态局部变量的区别:
(1)静态局部变量数据属于静态存储类别,在静态存储区内分配内存单元,在整个程序运行期间都不释放。而自动变量(即动态局部变量)属于动态存储类别,占动态存储区空间而不占
用静态存储区空间,函数调用结束后立即释放空间。
(2)静态局部变量时在编译时被赋值的,即自始至终只赋值一次,在程序运行时它已经有初值。以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值。而自动变量赋初值,不是在编译时进行的,而是在运行时进行,所以每调用一次函数就赋一次初值。
(3)如在定义局部变量时不赋初值,则对静态局部变量来说,编译时自动赋一个初值0(对数值型变量)或空字符(对字符变量)。而对自动变量来说,如果不赋初值,则它的值是一个不确定的值。这是由每次动态分配的内存单元不同所决定的。
static变量 ( 修饰全局变量 与 局部变量) 的例子:
-
/*在text.c文件中*/
-
int func_int()
-
{
-
return
2;
-
}
-
-
static
int func_static()
-
{
-
return
3;
-
}
-
/*在main.c文件中*/
-
#include<stdio.h>
-
void main()
-
{
-
int temp2 = func_int();
-
int temp3 = func_static();
-
printf(
"temp2 = %d\n",temp2);
-
printf(
"temp3 = %d\n",temp3);
-
}
//编译链接[root@node-2 C_function]# gcc main.c test.c
验证的时候可以先把 后面两行注释掉int temp3 = func_static(); printf("temp3 = %d\n",temp3);
***************结果显示如下*************
[root@node-2 C_function]# gcc main.c test.c
/tmp/ccg1gHfy.o: In function `main':
main.c:(.text+0x1b): undefined reference to `func_static'
collect2: error: ld returned 1 exit status
3、static修饰函数——静态函数(内部函数)
在函数前加static,则此函数成为静态函数(内部函数),我们用static修饰函数的主要目的是:用来表示不能被其它文件访问的一个函数(和用static修饰全局变量的目的一样,都是不允许其它文件访问)。这样一来便有一个好处:程序员不用担心自己编写的函数与其他文件的函数同名。(对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件)
参考的网址:
1》变量在内存中的存放区别:https://www.cnblogs.com/bakari/archive/2012/08/05/2623637.html
2》C\C++中STATIC的用法:https://www.cnblogs.com/jhmu0613/p/7131997.html
3》四个变量间的区别:https://www.cnblogs.com/zhangwuji/p/5297631.html
4》部分内存的分布情况:https://blog.csdn.net/jsjwql/article/details/1788286