从作用域上来说,C语言可以定义4种不同的变量:全局变量,静态全局变量,局部变量,静态局部变量。
下面仅从函数作用域的角度分析一下不同的变量,假设所有变量声明不重名。
- 全局变量,在函数外声明,例如,`int gVar;`。全局变量,所有函数共享,在任何地方出现这个变量名都是指这个变量。 除非在函数内部被重新声明定义,如下例代码。
- 静态全局变量,例如:`static sgVar;`。所有函数共享,但是这个会有编译器的限制,算是编译器提供的一种功能。
- 局部变量,例如函数/块内的`int var;`。不共享,函数的多次执行中涉及的这个变量都是相互独立的,他们只是重名的不同变量而已。
- 局部静态变量,函数中的`static int sVar;`。本函数内共享,函数的每一次执行中涉及的这个变量都是这个同一个变量。
# 全局变量
```c
int gVar = 0; // 全局变量
void gVarInr();
int main(int argc, char const *argv[]) {
int gVar = 10; // 局部变量
gVarInr();
printf("gVar is %d\n",gVar); // 10
gVarInr();
printf("gVar is %d\n",gVar); // 10
return 0;
}
void gVarInr()
{
gVar++;
printf("gVar is %d\n",gVar); // 1 2
}
```
打印结果
```
gVar is 1
gVar is 10
gVar is 2
gVar is 10
```
# 全局静态变量
全局变量之前再冠以 static 就构成了静态的全局变量。
## 存储方式
全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。
## 作用域区别
这两者的区别在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。
### 实例演示
文件1:`a.c`代码
```c
#include <stdio.h>
int a = 10;
```
文件2:`b.c`代码
```c
#include <stdio.h>
extern int a;
int main(int argc, char const *argv[]) {
printf("%d\n", a);
return 0;
}
```
在`b.c`使用 `extern` 引入`a.c`里面定义的全局变量`a`。编译
```
$ gcc a.c b.c -o test
$ ./test
10
```
### 修改为全局静态变量
```diff
#include <stdio.h>
- int a = 10;
+ static int a = 10;
```
再编译则提示
```
$ gcc a.c b.c -o test
Undefined symbols for architecture x86_64:
"_a", referenced from:
_main in bbb-616389.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
```
扩展:函数和静态函数也与之类似,函数默认是全局的,加了`static`之后,其作用域就只是本文件了。
# 局部变量
```c
#include <stdio.h>
void varInr();
int main(int argc, char const *argv[]) {
varInr();
varInr();
return 0;
}
void varInr()
{
int var = 0;
var++;
printf("var is %d\n",var);
}
```
打印结果
```js
var is 1
var is 1
```
这个大家都很熟悉了
# 局部静态变量
```diff
#include <stdio.h>
void varInr();
int main(int argc, char const *argv[]) {
varInr();
varInr();
return 0;
}
void varInr()
{
- int var = 0;
+ static int var = 0;
var++;
printf("var is %d\n",var);
}
```
打印结果
```js
var is 1
var is 2
```
上面几种作用域都是从函数的角度来定义作用域的,可以满足所有我们对单线程编程中变量的共享情况。
现在我们来分析一下多线程的情况。在多线程中,多个线程共享除函数调用栈之外的其他资源。 因此上面几种作用域从定义来看就变成了:
- 全局变量,所有函数共享,因此所有的线程共享,不同线程中出现的不同变量都是这同一个变量。
- 静态全局变量,所有函数共享,也是所有线程共享。
- 局部变量,此函数的各次执行中涉及的这个变量没有联系,因此,也是各个线程间也是不共享的。
- 静态局部变量,本函数间共享,函数的每次执行涉及的这个变量都是同一个变量,因此是各个线程共享的。
这对我们后期的线程安全编程非常有用。http://www.php-internals.com/book/?p=chapt08/08-03-zend-thread-safe-in-php