函数环境变量作用域

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 = ; void test_1(void)
{
int count = ;
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 ;
}

示例代码中,

函数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 = ;
for (; i < ; ++i)
{
test_1();
}
return ;
} void test_1(void)
{
static int count = ;
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 = ; int main(void)
{
int count = ;
int i = ;
for (; i < ; ++i)
{
test_1();
test_2();
}
printf("%d\n", ++count);
return ;
} void test_1(void)
{
static int count = ;
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 = ; int main(void)
{
int i = ;
if(i == ){
int test = ;
}
printf("%d\n", test);
}

示例代码中:

printf("%d\n", test);会抛出一个错误,因为test声明在if块作用域下,外层访问不到。

[C]变量作用域的更多相关文章

  1. javascript中的变量作用域以及变量提升

    在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解. 变量作用域 “一个变量的作用域表示这个变量存在的上 ...

  2. [转]深入理解JavaScript的变量作用域

    1.JavaScript的作用域链 2.函数体内部,局部变量的优先级比同名的全局变量高. 3.JavaScript没有块级作用域. 4.函数中声明的变量在整个函数中都有定义. 5.未使用var关键字定 ...

  3. Java基础知识笔记(七:接口、变量作用域和参数传递)

    一.接口 Java语言不允许一个子类拥有多个直接父类,即任何子类只能有一个直接父类.但允许一个类实现多个接口,即在定义类的接口名称列表中可以包含1个或多个接口名称,从而实现多重继承的特性.接口的定义格 ...

  4. PHP常量、变量作用域详解(一)

    PHP 中的每个变量都有一个针对它的作用域,它是指可以在其中访问变量(从而访问它的值)的一个领域.对于初学者来说,变量的作用域是它们所驻留的页面.因此, 如果你定义了 $var,页面余下部分就可以访问 ...

  5. PHP变量作用域详解(二)

    学过C的人用PHP的时候一般会相当顺手,而且感到PHP太方便太轻松.但在变量作用域这方面却与C有不同的地方,搞不好会相当郁闷,就找不到错误所在.昨晚就与到这么一个问题,是全局变量在函数中的问题.今天搜 ...

  6. JavaScript函数定义和调用 变量作用域

     本文是笔者在看廖雪峰老师JavaScript教程时的个人总结   JavaScript中函数定义可以是这样的格式 function 函数名(参数) {     函数体 } 也可以是这样的格式     ...

  7. JavaScript 变量作用域

    一. 变量声明 变量用var关键字来声明,如下所示: 变量在未声明的情况下被初始化,会被添加到全局环境. JavaScript执行代码时,会创建一个上下文执行环境,全局环境是最外围的环境.每个函数在被 ...

  8. 变量作用域&函数作用域

    一. 变量作用域 1)全局变量 在全局环境下声明的变量被视为全局变量. 在没有使用var进行声明的时候,变量就被定义为全局变量.在ES5的严格模式下,如果变量没有使用var来声明是会报错的. 2)局部 ...

  9. OC点语法和变量作用域

    OC点语法和变量作用域 一.点语法 (一)认识点语法 声明一个Person类: #import <Foundation/Foundation.h> @interface Person : ...

  10. python的变量作用域问题

    偶然掉进了一个坑里.仔细分析了下原因.原来是变量作用域的问题.简单抽象如下: id=1 #许多行代码 [id for id in range(10)] #许多行代码 if id!=1: #做一些事情 ...

随机推荐

  1. Python高性能编程

    一.进程池和线程池 1.串行 import time import requests url_lists = [ 'http://www.baidu.com', 'http://fanyi.baidu ...

  2. Django-GET和POST小记

    import requests requests.get(url='xxx') # 本质上就是: requests.request(method='get',url='xxx') import jso ...

  3. C++模板的使用以及常见问题

    最近的数据结构实验频繁地遇到了模板,之前对这一块接触不多,遇到了很多问题,放到这里总结一下. 模板的声明有两种:template <typename Type>或者template< ...

  4. vue插件 使用use注册Vue全局组件和全局指令

    插件一般会注册到全局使用 官方编辑插件介绍:https://vuefe.cn/v2/guide/plugins.html 全局组件: .首先建一个自定义组件的文件夹,比如叫loading,里面有一个i ...

  5. Greendao 缓存问题

    GreenDao在使用过程中如果查询数据后,修改数据,再次查询的话,使用的是刚才修改后的数据,为了避免这个问题,要清除缓存,清除缓存有两种方法 1.daoSession.clear(); 2.dao. ...

  6. VS2010显示行号

    选项->文本编辑器->如果使用C#开发选择C#->勾选行号->确定

  7. 三十五、minishell(3)

    35.1 内容 在当前的 minishell 中,如果执行 date clear 命令等,minishell 会停止: 这是因为引入进程组的时候,mshell 放置在前台进程组,同时之后在子进程中又创 ...

  8. 四、文件IO——内核数据结构和原子操作

    4.1 缓存 buff 说明 一般设置缓存 buff  的大小是由一定的规律的,就是根据磁盘块的大小来定. Linux下输入命令: df -k  查看磁盘 可以用命令查看下 /dev/sda1 磁盘的 ...

  9. Commons Lang 介绍

    https://commons.apache.org/proper/commons-lang/ https://commons.apache.org/proper/commons-lang/javad ...

  10. springboot13 发布和监听事件

    spring中的事件驱动模型Event(也叫发布订阅模式),是观察者模式的一个典型的应用 好处:业务解耦,在不影响原来业务逻辑的情况下,加入其它业务 场景: app上线后已实现用户注册功能,现需要在用 ...