C static静态变量使用研究

0x01隐藏

当我们同时编译多个文件时,所有未加 static 前缀的全局变量和函数都具有全局可见性。为理解这句话,我举例来说明。我们要同时编译两个源文件,一个是 a.c,另一个是 main.c。

下面是 a.c 的内容:

char a = 'A'; // global variable
void msg()
{
    printf("Hello
");
}

下面是 main.c 的内容:

int main(void)
{    
    extern char a;    // extern variable must be declared before use
    printf("%c ", a);
    (void)msg();
    return 0;
}

程序的运行结果是:

A Hello

如果加了 static,就会对其它源文件隐藏。例如在 a 和 msg 的定义前加上 static,main.c 就看不到它们了。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。static 可以用作函数和变量的前缀,对于函数来讲,static 的作用仅限于隐藏。

有的公司编码规范明确规定只用于本文件的函数要全部使用static关键字声明,这是一个良好的编码风格。

0x02持久

存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和 static 变量,只不过和全局变量比起来,static 可以控制变量的可见范围,说到底 static 还是用来隐藏的。虽然这种用法不常见例如下面这段代码

#include <stdio.h>

void fun(int n)
{
    static int nTest = n;

    printf("%d
", nTest);
    printf("%p
", &nTest);

    

}

void main()
{
    fun(1);
    fun(2);
    fun(3);
    fun(4);

}

运行结果

1
0085B14C
1
0085B14C
1
0085B14C
1
0085B14C

没有改变,值得注意的是在vs调试运行时直接查看反汇编

 在vc++ 上这里查看的反汇编是空 其实可以理解为在赋值一次后就不做操作了 。

下个断点看看他的内存改变

可以看到在下一步时 第一个int字节 位置 被写入了01(int 4个字节)  下一个是他的初始标识被同时改为1

再次段步后我直接把内存下标01改成00

 在执行就是

 执行结果

1
0085B14C
2
0085B14C
2
0085B14C
2
0085B14C

也就是说他通过标识来判断是否是赋过值

 那我们来执行下面这段代码

#include <stdio.h>

void fun(int n)
{
    static int nTest = n;

    printf("%d
", nTest);
    printf("%p
", &nTest);

    (&nTest)[1] = 0;
    (&nTest)[2] = 0;

}

void main()
{
    fun(1);
    fun(2);
    fun(3);
    fun(4);

}

把这个静态变量的后面2个int 字节赋0 他的运行结果就是

1
005AB14C
2
005AB14C
3
005AB14C
4
005AB14C

以上环境在vs2017上 13和vc6 都只用改 当然有的可能下标距离很远

(&nTest)[1] = 0;

0x03初始化

其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是 0x00,某些时候这一特点可以减少程序员的工作量。比如初始化一个稀疏矩阵,我们可以一个一个地把所有元素都置 0,然后把不是 0 的几个元素赋值。如果定义成静态的,就省去了一开始置 0 的操作。再比如要把一个字符数组当字符串来用,但又觉得每次在字符数组末尾加  太麻烦。如果把字符串定义成静态的,就省去了这个麻烦,因为那里本来就是  。

#include <stdio.h>

int a;

int main(void)
{
    int i;
    static char str[10];

    printf("integer: %d;  string: (begin)%s(end)", a, str);

    return 0;
}

程序的运行结果如下

integer: 0; string: (begin)(end)

最后对 static 的三条作用做一句话总结。首先 static 的最主要功能是隐藏,其次因为 static 变量存放在静态存储区,所以它具备持久性和默认值0。

从此山高路远,纵马扬鞭。愿往后旅途,三冬暖,春不寒,天黑有灯,下雨有伞。此生尽兴,不负勇往。
原文地址:https://www.cnblogs.com/feizianquan/p/14653838.html