小甲鱼 发表于 2014-5-11 13:38:26

第002讲:【*】使用 static 的三个理由

转自:http://www.cnblogs.com/dc10101/archive/2007/08/22/865556.html

在 C 语言中,static 的字面意思很容易把我们导入歧途,其实它的作用有三条。



(1)先来介绍它的第一条也是最重要的一条:隐藏

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

下面是 a.c 的内容
char a = 'A'; // global variable
void msg()
{
    printf("Hello\n");
}
下面是main.c的内容
int main(void)
{   
    extern char a;    // extern variable must be declared before use
    printf("%c ", a);
    (void)msg();

    return 0;      
}
程序的运行结果是:

A Hello

你可能会问:为什么在 a.c 中定义的全局变量 a 和函数 msg 能在 main.c 中使用?前面说过,所有未加 static 前缀的全局变量和函数都具有全局可见性,其它的源文件也能访问。此例中,a 是全局变量,msg 是函数,并且都没有加 static 前缀,因此对于另外的源文件 main.c 是可见的。

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


(2)static 的第二个作用是保持变量内容的持久

存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。

共有两种变量存储在静态存储区:全局变量和 static 变量,只不过和全局变量比起来,static可以控制变量的可见范围,说到底static还是用来隐藏的。虽然这种用法不常见,但我还是举一个例子。

#include <stdio.h>

int fun(void)
{
    static int count = 10;    // 事实上此赋值语句从来没有执行过
    return count--;
}

int count = 1;

int main(void)
{   
    printf("global\t\tlocal static\n");
    for(; count <= 10; ++count)
      printf("%d\t\t%d\n", count, fun());   
   
    return 0;
}
程序的运行结果是:

global      local static

1               10

2               9

3               8

4               7

5               6

6               5

7               4

8               3

9               2

10             1


(3)static 的第三个作用是默认初始化为 0

其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是 0x00,某些时候这一特点可以减少程序员的工作量。比如初始化一个稀疏矩阵,我们可以一个一个地把所有元素都置 0,然后把不是 0 的几个元素赋值。如果定义成静态的,就省去了一开始置 0 的操作。

再比如要把一个字符数组当字符串来用,但又觉得每次在字符数组末尾加 '\0' 太麻烦。如果把字符串定义成静态的,就省去了这个麻烦,因为那里本来就是 '\0'。不妨做个小实验验证一下。

#include <stdio.h>

int a;

int main(void)
{
    int i;
    static char str;

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

    return 0;
}
程序的运行结果是:

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

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


myisland 发表于 2014-5-11 14:37:12

学习了,多谢楼主分享!

C_program 发表于 2014-5-11 17:11:19

static 隐藏 没有看明白

C_program 发表于 2014-5-11 17:13:10

具体隐藏了什么?

小甲鱼 发表于 2014-5-11 21:33:24

C_program 发表于 2014-5-11 17:13 static/image/common/back.gif
具体隐藏了什么?

如果加了 static,就会对其它源文件隐藏。例如在 a 和 msg 的定义前加上 static,main.c 就看不到它们了。

Penn 发表于 2014-5-11 22:54:01

大赞甲鱼。。

C_program 发表于 2014-5-12 18:52:17

小甲鱼 发表于 2014-5-11 21:33 static/image/common/back.gif
如果加了 static,就会对其它源文件隐藏。例如在 a 和 msg 的定义前加上 static,main.c 就看不到它们了。 ...

非常感谢 甲鱼哥 我明白了

E=MC2 发表于 2014-5-13 11:34:48

#include <stdio.h>
int a;
int main(void)
{       
          int i;       
               char str={'A','B','C'};
              // static char str={'A','B','C'};       
                   printf("integer: %d;string: (begin)%s(end)", a, str);       
                  return 0;       
        }甲鱼老师! 你看这个加不加static都一样啊! 都能正确输出ABC。感觉字符数组应该是没有显示初始化字符,那后面几个数组元素自动补0的。

Victory_6226 发表于 2014-5-13 11:43:26

static int count = 10;    // 事实上此赋值语句从来没有执行过

这句话什么意思?在初次运行的时候进行过一次初始化吧,后续的调用就不再初始化了吧

迷雾少年 发表于 2014-5-17 07:01:02

非常感谢 甲鱼哥 我明白了

sbwcwusi 发表于 2014-5-21 13:19:19

数组初始化。。你没学好char str={'A','B','C'};
默认其它元素初始化零

purplepower99 发表于 2014-6-1 22:16:56

真是长见识了,谢谢小甲鱼!

964859557 发表于 2014-6-6 22:06:51

一直记到static的前两个作用,却忘了最后的初始化为0的作用了,就当复习一下

沉思的牛 发表于 2014-6-9 18:41:27

今天又涨姿势了:lol:

小溪青石 发表于 2014-6-19 20:31:15

应该是只执行了一次,从未执行就不对了吧。

我是桃川人 发表于 2014-6-22 13:41:51

总结看完就明白了。

赵得伟 发表于 2014-7-20 19:01:52

C_program 发表于 2014-5-11 17:13
具体隐藏了什么?

隐藏了之后,你在main函数中   加上了extern的外部申明也不能调用它,明白了嘛?

赵得伟 发表于 2014-7-20 19:05:49

E=MC2 发表于 2014-5-13 11:34
甲鱼老师! 你看这个加不加static都一样啊! 都能正确输出ABC。感觉字符数组应该是没有显示初始化字符,那 ...

这个不一样,你在定义静态字符数组时候已经给他初始化了!!
而且字符数组输出的结束标志就是   判断最后一个元素是否为0   当str【3】 = 0时就出来啦!

E=MC2 发表于 2014-7-20 21:38:51

赵得伟 发表于 2014-7-20 19:05
这个不一样,你在定义静态字符数组时候已经给他初始化了!!
而且字符数组输出的结束标志就是   判断最 ...

你的意思是#include <stdio.h>
int a;
int main(void)
{            
        char str;//没有初始化
    //static char str; //已经初始化      
        printf("integer: %d;string: (begin)%s(end)", a, str);
        return 0;      
}

gauss 发表于 2014-10-1 14:49:47

了解。
页: [1] 2 3
查看完整版本: 第002讲:【*】使用 static 的三个理由