深入挖掘 C 语言 static 关键字

2020-02-18

C 语言的 static 关键字与其他面向对象语言中的 static 并不一样 。做个笔记,以防忘记。

搜索一下就知道了,C 语言中的 static 有两个作用,修饰变量修饰函数 ,以下具体来分析。

修饰变量

static 修饰的变量成为 静态变量 ,那么什么是静态变量 呢?

我们知道,函数内的变量,其生命周期随函数存在,也就是函数调用过后,变量也就销毁了。所谓静态变量,就是不随函数销毁而销毁的变量。

代码示例就很清晰:

#include <stdio.h>
void foo()
{
    int normal_var = 0;
    static int static_var = 0;
    normal_var += 5;
    static_var += 5;
    printf("normal_var = %d, static_var = %d\n", normal_var , static_var);
}
int main()
{
    int i;

    for (i = 0; i < 3; ++i){
        foo();
    }
}

运行得到:

normal_var = 5, static_var = 5
normal_var = 5, static_var = 10
normal_var = 5, static_var = 15

可知,对于普通变量每次函数调用重新分配,调用结束则销毁,所以 normal_var 一直是5;而被 static 修饰的变量,不随函数销毁而销毁,所以每次函数调用都能在上一次基础上累加。

静态变量存储

这里在稍微深入一下,从内存的角度来看 静态变量 为什么不随函数调用而销毁的?

我们知道,一个函数调用,其拥有一块内存函数栈 ,函数内的变量都存放在栈内存中,函数调用结束这块内存即被回收,变量也就不复存在。那么可判断静态变量并不和普通变量一样存在此处,那么它存在哪呢?

答案是:它存在整个程序的数据段(.data)中,这里引用《程序员的自我修养:装载、链接和库》的描述:

.data 段保存的是那些已经初始化了的全局静态变量和局部静态变量。

所以静态变量 的声明周期是跟随程序的运行周期的,不会随着函数调用而销毁。

修饰函数

static 关键字还可以修饰函数,表名函数只能在当前文件中可见。什么意思?用代码表示一下就很清晰

// a.h 文件:
static int add(int a, int b );
void call_add();

// a.c 
#include <stdio.h>

static int add(int a, int b ){
    return a + b;
}

void call_add(){
    printf("I can call_add in this %d\n",add(10,20));
}

在 a.c 文件内,add 函数被标记为 static 表示它只能被当前文件的函数调用。也就是 call_add 函数能调用它。

如果有另一个文件 b.c :

#include "a.h"
int main(int argc, char *argv[]){
    call_add(10,20);
        //add(10,20) ; 不能调用,因为 add 为 static
    return 0;
}

在 b.c 中,是不能调用 add 函数的,这就是static 的意义所在,而其可以通过调用 a 文件的 call_add 来实现简介调用add 。 因为 call_add 是能够调用 add 的。

黔ICP备17000852号-4