[C]变量作用域
函数环境变量作用域
C语言栈环境变量作用域跟JS是类似的。
就是内部函数可以访问外部函数的执行(栈)环境变量。
当访问一个变量时,程序将会查询当前栈环境是否存在这个变量,如果没有,将会往上层栈环境继续查找,直到找到该变量为止。
#include <stdio.h> #include <stdlib.h> #include <string.h> void test_1(void); void test_2(void); void test_3(void); int main(void) { int count = 2; void test_1(void) { int count = 5; printf("%d\n", ++count); } void test_2(void) { printf("%d\n", ++count); void test_3(void) { printf("%d\n", ++count); } test_3(); } test_1(); test_2(); return 0; }
示例代码中,
函数test_1由于栈环境内部声明了变量count,所以输出了当前变量++count,即等于5,不再往上查找。
函数test_2在第一句中访问了变量count,由于在它自身栈环境中不存在变量count,所以它将会往上一层查找main函数中是否存在count,因为main确实存在变量count,所以给它递增了1,此时count变成了3。
函数test_3的查找方式也是类似的,由于自身栈环境找不到count,所以它将会往上一层查找test_2函数中是否存在count,发觉test_2也不存在count,再往上一层查找,直到找到count为止,最终在main找到了count,此时函数给它再递增1,count的值变成了4。
static关键字
C语言static关键字跟PHP是类似的。
栈环境退出后,static关键字的变量不会被销毁。
如果是初次进入栈环境,这个变量将会被初始化为声明语句赋予的值。
如果是再次进入栈环境,则采用上一次运行后产生的值。
#include <stdio.h> #include <stdlib.h> #include <string.h> void test_1(void); int main(void) { int i = 0; for (; i < 3; ++i) { test_1(); } return 0; } void test_1(void) { static int count = 2; printf("%d\n", ++count); }
示例代码中:
函数test_1被执行了3次。
第一次执行时,静态变量count被初始化为2,在下一句中被递增1,然后退出环境,但此时count并不会被销毁。
第二次执行时,由于上一次执行的时候count已经初始化了,所以此时count使用的是上一次栈环境退出时保存下来的值。
第三次执行过程雷同。
结果三次依次输出了3,4,5;
总结示例
#include <stdio.h> #include <stdlib.h> #include <string.h> void test_1(void); void test_2(void); int count = 0; int main(void) { int count = 10; int i = 0; for (; i < 3; ++i) { test_1(); test_2(); } printf("%d\n", ++count); return 0; } void test_1(void) { static int count = 20; printf("%d\n", ++count); } void test_2(void) { printf("%d\n", ++count); }
示例代码中:
main访问了栈内部定义的count。
test_1访问了栈内部定义的静态变量count。
test_2访问了栈外部(这里是全局变量)的count。
最终输出结果是21,1,22,2,23,3,11。
误区
当函数f内部访问另外一个函数c,函数c的外部栈环境不一定是f哦。
栈环境是谁,取决于函数编写在哪个位置。
例如上述示例代码,test_1,test_2的栈环境是全局环境,并不是main哦,main只是调用了它们而已。
块作用域
C语言有块作用域。
在{}区域下声明的变量,只有在这个区域下才可以访问。
#include <stdio.h> #include <string.h> int count = 0; int main(void) { int i = 1; if(i == 1){ int test = 2; } printf("%d\n", test); }
示例代码中:
printf("%d\n", test);会抛出一个错误,因为test声明在if块作用域下,外层访问不到。