1. 概述
static关键字在c语言中比较常用,使用恰当能够大大提高程序的模块化特性,有利于扩展和维护。
2. static修饰局部变量(C/C++)
普通局部变量是最常见的一种变量,在任何一个函数内部定义的变量(不加static修饰符)都属于这个范畴。如果不对普通局部变量进行显式的初始化,则编译器也不会对其自动进行初始化,也就是说它的值在初始时是不确定的。 且普通局部变量存储于进程栈空间,离开作用域会立即释放。
静态局部变量使用static修饰符定义,即使在定义时未赋初值,编译器也会将其初始化为0值(根据数据类型的不同可能会稍有不同)。且静态局部变量存储于进程的数据段,即使函数返回,它的值也会保持不变。
可以说其作用域为局部作用域,当定义它的函数结束时,其作用域随之结束。但相比于不加static修饰它的生命周期被延长。
#include <stdio.h>
void fun() {
static int x = 10;
printf("%d\n", ++x);
}
int main(int argc, char const *argv[])
{
fun();
fun();
fun();
}
// Output:
// 11
// 12
// 13
由输出可知,虽然fun函数结束了,但x并没有被销毁,下次进入fun函数时x还保持着上一次结束时的值。
但如果尝试在main函数中直接输出x的值,编译器会报错x未定义,这说明了x虽然生命周期被延长了,但作用域仍然是原函数范围内,这是静态局部变量和全局变量的不同之处。
C和C++在静态局部变量上稍有不同,C语言的静态局部变量必须用常量来初始化,而C++则无此限制。
3. static修饰全局变量(C/C++)
全局变量定义在函数体外部,在数据段分配存储空间,且编译器会自动对其初始化。
普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)。
静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响。
在定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用。
4. static修饰函数
函数的使用方式与全局变量类似,在函数的返回类型前加上static,就是静态函数。其特性如下:
- 静态函数只能在声明它的文件中可见,其他文件不能引用该函数
- 不同的文件可以使用相同名字的静态函数,互不影响
非静态函数可以在另一个文件中直接引用,甚至不必使用extern声明.
5. static修饰C++成员变量
- 静态成员变量为所有类对象所共享,不独属于某个对象。
- 静态成员变量必须在类定义外的相同作用域内被初始化后,才能访问,初始化时带上类型,不带static关键字。
- 对类计算
sizeof
的时候不计算静态成员变量,因为其存储在数据段。 - 静态成员变量不能在成员初始化列表处初始化。
- 类静态成员可用
类名::静态成员
或者对象.静态成员
来访问。 - 静态成员变量同样具有
public
、protected
和private
三种访问级别。
6. static修饰C++成员函数
- 静态成员函数可以通过
类名::静态成员函数
或者对象.静态成员函数
来访问。 - 静态成员函数没有隐藏的
this
指针,不能访问任何非静态成员,所以同样也不能加const
修饰静态成员函数。 - 静态成员函数同样具有
public
、protected
和private
三种访问级别。 - 静态成员函数不能调用非静态成员函数,因为无法传递
this
指针。 - 非静态成员函数可以调用静态成员函数。