C笔记-坑爹的关键字static

作者:聂勇 欢迎转载,请保留作者信息并说明文章来源!

熟悉了面向对象的Java语言,因工作需要,转向PHP这种半面向对象半面向过程的语言时,发现一些面向对象的设计在PHP中行不通,只能采用变通的方式。现在学习Unix C编程,完全面向过程,让人更加痛苦。而且,前面的一些概念惯性,在学习C的过程中踩了不少陷井。关键字static就是其中一个。

Java中的static

在Java中,static关键字用来修饰方法,变量和代码块,称为静态方法,静态变量和静态代码块。

  • 静态方法:独立于实例,可通过类名直接调用,不可抽象,必须被实现。不可访问实例中的变量和方法。
  • 静态变量:在JVM内存中只有一份拷贝,在类的加载过程中完成。可通过类名来调用。
  • 静态代码块:由JVM在加载类时执行,在一个JVM进程中只会执行一次。

C中的static

在C中,static关键字可以用来修饰方法和变量,称为静态方法和静态变量。

  • 静态方法:方法只在当前文件中可见,起到模块解耦的作用。
  • 静态变量:变量存放在程序的全局存储区中,下一次调用时会保存着上一次的值;仅在自己的作用范围内可见,静态局部变量仅在当前方法可见,静态全局变量仅在当前文件可见。

1、静态局部变量

1)保存上一次的值。
a.c 源文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <stdlib.h>
void runLocalStaticVar(void)
{
static int a = 5; // 赋值只会执行一次
int b = 5; // 赋值每次都会执行
a ++;
printf("a=%d, b=%d\n", a, b);
}
int main(int argc, char *argv[])
{
int x = 0;
for(x=0; x<5; x++)
{
runLocalStaticVar();
}
return EXIT_SUCCESS;
}

执行结果如下:

a=6, b=5
a=7, b=5
a=8, b=5
a=9, b=5
a=10, b=5

2、静态全局变量

1)可见性:仅在当前文件可见。
b.h 源文件:

1
void runGlobalStaticVar(void);

b.c 源文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
#include "b.h"
static int a = 5; // 定义了静态全局变量
int b = 5;
static void hello(void) // 定义了静态方法
{
printf("say hello\n");
}
void runGlobalStaticVar(void)
{
a ++;
b ++;
printf("a=%d, b=%d\n", a, b);
hello();
}

c.c 源文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#include <stdlib.h>
// extern static int a; // 如果启用这行,在编译的时候将报错:error: multiple storage classes in declaration specifiers
// extern int a;
extern int b;
void runGlobalStaticVarAgain(void)
{
// a ++; // 如果将这行与extern int a; 一同启用,在编译时将报错:undefined reference to `a'
b ++;
printf("b=%d\n", b);
}
int main(int argc, char *argv[])
{
int x = 0;
for(x=0; x<5; x++)
{
runGlobalStaticVar();
}
printf("------------------\n");
for(x=0; x<5; x++)
{
runGlobalStaticVarAgain();
}
// hello(); 如果启用这行,编译时将报错:warning: implicit declaration of function ‘hello’ 和 undefined reference to `hello'
return EXIT_SUCCESS;
}

编译命令:

1
gcc -Wall -o d b.c c.c

执行结果如下:

a=6, b=6
say hello
a=7, b=7
say hello
a=8, b=8
say hello
a=9, b=9
say hello
a=10, b=10
say hello
-—————–
b=11
b=12
b=13
b=14
b=15