zoukankan      html  css  js  c++  java
  • 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。

    从此山高路远,纵马扬鞭。愿往后旅途,三冬暖,春不寒,天黑有灯,下雨有伞。此生尽兴,不负勇往。
  • 相关阅读:
    LCT男人八题系列
    hadoop 伪分布启动-fs格式化
    hadoop 安装
    Scala Actor入门
    Scala 隐式转换和隐式参数
    Scala 类型参数
    Scala 类型参数
    Scala 匹配模式
    scala 函数式编程之集合操作
    Scala 函数式编程
  • 原文地址:https://www.cnblogs.com/feizianquan/p/14653838.html
Copyright © 2011-2022 走看看