在学习volatile关键字时,在此重温下C语言的其他关键字static。 这个关键字可以说到处都在用,但是能否详细说清楚这个static应该怎么用,什么场景用,怎么用合适?当你写下static的时候,是否考虑了真的需要用static吗?
在前面笔记中也有学习了static, 但明显感觉得出来,当时对static的理解不到位。
目录
一 static关键字
static是C/C++中的修饰符,用来修饰变量或函数
二 static关键字的使用
- 修饰局部变量 -- 静态局部变量
- 修饰全局变量 -- 静态全局变量
- 修饰函数 -- 静态函数
三 static关键字的具体使用
1、修饰局部变量
(1)不使用 static 修饰局部变量,结果如下:
(2)使用 static 修饰局部变量,结果如下:
输出不同结果的原因:
(1)static 修饰局部变量,改变了局部变量的存储属性(变为静态局部变量),通过改变存储属性来改变他的生命周期。
(2)局部变量原本存储在内存的栈区,被static 修饰之后的局部变量存储在内存的静态区
(3)在局部作用域结束时,被static 修饰的变量并没有销毁,等下一次进入局部作用域时就会延用上一次的结果值
(4)注:被static 修饰的局部变量的作用域不会被改变,依旧只能在定义的作用域范围内使用。
所以 static 修饰局部变量的作用是:改变局部变量的生命周期,本质上是改变了局部变量的存储位置,让局部变量不再是在栈区上开辟空间,而是直接在静态区上开辟空间,从而使得局部变量拥有和全局变量一样的生命周期,即随着整个程序生成和销毁。
如下:
普通的数据是放在内存的栈区上,会受到自己作用域的限制,进入作用域生效,出了作用域失效。
当被 static 修饰的时候,数据则是在静态区存储的的,这时存储的数据,出了作用域变量不会销毁,得到了持久化。
本质实际是改变了存储位置:栈区--->静态区,使得数据的生命周期发生了变化。
引入内存:
内存包括三个区(栈区,堆区,静态区)
- 栈区(局部变量,函数的形式参数--临时的变量)
- 堆区(动态内存分配,malloc,calloc,realloc,free)
- 静态区(静态变量,全局变量)
注意:这只是一种粗略,简单的划分。
局部变量分配在栈区,全局变量分配在静态区。
2、修饰全局变量
(1)未被static修饰
(2)被static 修饰的全局变量
输出结果失败的原因:
- 全局变量具有外部性链接属性;被static 修饰的全局变量转变为内部性链接属性,被私有化(被static 修饰的全局变量,只能在自己所在的源文件.c内部才可以被使用)
·普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)。
·静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响。
在定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用。
3、修饰函数
(1)未被static 修饰的函数
(2)被static 修饰的函数
输出结果失败的原因:
- 函数具有外部性链接属性;被static 修饰的函数转变为内部性链接属性,被私有化(被static 修饰的函数,只能在自己所在的源文件.c内部才可以被使用)
四: 总结
(1)static修饰局部变量
应用:在函数内,我们想保留某些变量上一次的值,就可以用static去修饰该变量。比如:想统计该函数被执行的次数时,就可以定义被static修饰的int型变量,每执行一次该变量就++。
总结:用static修饰的局部变量,改变了生存周期,但是没有改变其作用域。改变其生存周期的原因是被static修饰的局部变量被存放在.bss段(未初始化)或者 .data段(初始化),但两者都是在(全局区)静态区,而普通的局部变量是存放在栈上的。
(2)static修饰全局变量
应用:当一个全局变量不想被其他.c文件引用时,可以用static修饰,这样其他的文件就不能通过extern的方式去访问,这样主要是为了数据安全。
以 static 修饰全局变量的作用是:改变了全局变量的外部链接属性(可以在其他源文件内被访问),使其变成内部连接属性(只能在本文件内部被访问),给我们的感觉是全局变量的作用域变小了。
总结:改变其作用域,作用域变小,没有改变生存周期。
(3) static修饰函数
应用:有些函数并不想对外提供,只需要在本文件里调用,这时候就可以用static去修饰。
所以 static 修饰函数的作用是:改变了函数的外部链接属性(可以在其他源文件内被访问),使其变成内部连接属性(只能在本文件内部被访问),给我们的感觉是函数的作用域变小了。
总结:改变了作用域,作用域变小,没有改变其生存周期。
(4)
用static修饰全局变量和函数,除了上面说的数据安全,防止被误引用。
还有一个作用是解决重名问题。当用static修饰了全局变量和函数后,其他文件里再定义同名的全局变量和函数也是可以的。一般来说,如果不是要对外提供的函数和全局变量,最好都用static修饰。
五:总结2
总结
static 全局变量与普通的全局变量有什么区别 ?
① 全局变量(外部变量)的声明之前再冠以 static 就构成了静态的全局变量,全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式,所以这两者在存储方式上并无不同
② 这两者的区别在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的,而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它,由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误
static 局部变量和普通局部变量有什么区别 ?
① 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期,而把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围
② static 全局变量只定义并初使化一次,防止在其他文件单元中被引用
static 函数与普通函数有什么区别?
① static 函数与普通函数作用域不同,仅在本文件有效,只在当前源文件中使用的函数应该声明为内部函数(static 修饰的函数),内部函数应该在当前源文件中说明和定义,对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件
② static 函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝
extern 全局变量、static 全局变量和 static 局部变量的生存期都是“永久”,区别只是可见域不同。extern 全局 变量可见区域是工程,static 全局变量可见区域是文件,而 static 局部变量的可见区域是块。从代码维护角度来看,对extern 变量的修改可能会影 响所有代码,对 static 全局变量的修改可能影响一个文件 中的代码,而对static 变量的修改 可能影响一个块的代 码;因此在选择变量类型时,优先级是 static 局 部>static 全局>extern 全局。
一个变量不能同时用extern和static同时修饰。
帖子:
https://blog.csdn.net/weixin_64051585/article/details/130254496 -----非常清晰,下面这几个帖子也都非常好,
https://blog.csdn.net/lin_95/article/details/130328142
https://blog.csdn.net/weixin_59511824/article/details/131292512
https://blog.csdn.net/taozou221B/article/details/130226793
https://blog.csdn.net/m0_64565155/article/details/132488724