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的时候不计算静态成员变量,因为其存储在数据段。
  • 静态成员变量不能在成员初始化列表处初始化。
  • 类静态成员可用类名::静态成员或者对象.静态成员来访问。
  • 静态成员变量同样具有publicprotectedprivate三种访问级别。

6. static修饰C++成员函数

  • 静态成员函数可以通过类名::静态成员函数或者对象.静态成员函数来访问。
  • 静态成员函数没有隐藏的this指针,不能访问任何非静态成员,所以同样也不能加const修饰静态成员函数。
  • 静态成员函数同样具有publicprotectedprivate三种访问级别。
  • 静态成员函数不能调用非静态成员函数,因为无法传递this指针。
  • 非静态成员函数可以调用静态成员函数。
Last modification:November 10th, 2019 at 10:10 am