C语言函数的作用域规则
“语言的作用域规则”是一组确定一部分代码是否“可见”或可访问另一部分代码和数据的规则。
“同一函数中,不同的结构体成员名能相同,当变量处于不同的作用域时,名称可以相同。
注:作用域,其对象是变量,而非表达式。”
C语言中的每一个函数都是一个独立的代码块。一个函数的代码块是隐藏于函数内部的,不能被任何其它函数中的任何语句(除调用它的语句之外)所访问(例如,用g o t o语句跳转到另一个函数内部是不可能的)。构成一个函数体的代码对程序的其它部分来说是隐蔽的,它既不能影响程序其它部分,也不受其它部分的影响。换言之,由于两个函数有不同的作用域,定义在一个函数内部的代码数据无法与定义在另一个函数内部的代码和数据相互作用。C语言中所有的函数都处于同一作用域级别上。这就是说,把一个函数定义于另一个函数内部是不可能的。
4.2.1 局部变量
对于局部变量,要了解的最重要的东西是:它们仅存在于被定义的当前执行代码块中,即局部变量在进入模块时生成,在退出模块时消亡。
定义局部变量的最常见的代码块是函数。例如,考虑下面两个函数。
整数变量x被定义了两次,一次在func1()中,一次在func2()中。func1()和func2()中的x互不相关。其原因是每个x作为局部变量仅在被定义的块内可知。
语言中包括了关键字auto,它可用于定义局部变量。但自从所有的非全局变量的缺省值假定为auto以来,auto就几乎很少使用了,因此在本书所有的例子中,均见不到这一关键字。
在每一函数模块内的开始处定义所有需要的变量,是最常见的作法。这样做使得任何人读此函数时都很容易,了解用到的变量。但并非必须这样做不可,因为局部变量可以在任何模块中定义。为了解其工作原理,请看下面函数。
这里的局部变量s就是在if块入口处建立,并在其出口处消亡的。因此s仅在if块中可知,而在其它地方均不可访问,甚至在包含它的函数内部的其它部分也不行。
在一个条件块内定义局部变量的主要优点是仅在需要时才为之分配内存。这是因为局部变量仅在控制转到它们被定义的块内时才进入生存期。虽然大多数情况下这并不十分重要,但当代码用于专用控制器(如识别数字安全码的车库门控制器)时,这就变得十分重要了,因为这时随机存储器(RAM)极其短缺。
由于局部变量随着它们被定义的模块的进出口而建立或释放,它们存储的信息在块工作结束后也就丢失了。切记,这点对有关函数的访问特别重要。当访问一函数时,它的局部变量被建立,当函数返回时,局部变量被销毁。这就是说,局部变量的值不能在两次调用之间保持。
4.2.2全局变量
与局部变量不同,全局变量贯穿整个程序,并且可被任何一个模块使用。它们在整个程序执行期间保持有效。全局变量定义在所有函数之外,可由函数内的任何表达式访问。在下面的程序中可以看到,变量count定义在所有函数之外,函数main()之前。但其实它可以放置在任何第一次被使用之前的地方,只要不在函数内就可以。实践表明,定义全局变量的最佳位置是在程序的顶部。
仔细研究此程序后,可见变量count既不是main()也不是func1()定义的,但两者都可以使用它。函数func2()也定义了一个局部变量count。当func2访问count时,它仅访问自己定义的局部变量count,而不是那个全局变量count。切记,全局变量和某一函数的局部变量同名时,该函数对该名的所有访问仅针对局部变量,对全局变量无影响,这是很方便的。然而,如果忘记了这点,即使程序看起来是正确的,也可能导致运行时的奇异行为。
全局变量由C编译程序在动态区之外的固定存储区域中存储。当程序中多个函数都使用同一数据时,全局变量将是很有效的。然而,由于三种原因,应避免使用不必要的全局变量:
①不论是否需要,它们在整个程序执行期间均占有存储空间。②由于全局变量必须依靠外部定义,所以在使用局部变量就可以达到其功能时使用了全局变量,将降低函数的通用性,这是因为它要依赖其本身之外的东西。③大量使用全局变量时,不可知的和不需要的副作用将
可能导致程序错误。如在编制大型程序时有一个重要的问题:变量值都有可能在程序其它地点偶然改变。
结构化语言的原则之一是代码和数据的分离。C语言是通过局部变量和函数的使用来实现这一分离的。下面用两种方法编制计算两个整数乘积的简单函数mul()。
通用的专用的
mul(x,y) intx,y;
intx,y; mul()
{{
return(x*y);return(x*y);
}}
两个函数都是返回变量x和y的积,可通用的或称为参数化版本可用于任意两整数之积,而专用的版本仅能计算全局变量x和y的乘积。
4.2.3动态存储变量
从变量的作用域原则出发,我们可以将变量分为全局变量和局部变量;换一个方式,从变量的生存期来分,可将变量分为动态存储变量及静态存储变量。
动态存储变量可以是函数的形式参数、局部变量、函数调用时的现场保护和返回地址。
这些动态存储变量在函数调用时分配存储空间,函数结束时释放存储空间。动态存储变量的定义形式为在变量定义的前面加上关键字“auto”,例如:
auto int a,b,c;
“auto”也可以省略不写。事实上,我们已经使用的变量均为省略了关键字“auto”的动态存储变量。有时我们甚至为了提高速度,将局部的动态存储变量定义为寄存器型的变量,定义的形式为在变量的前面加关键字“register”,例如:
register int x,y,z;
这样一来的好处是:将变量的值无需存入内存,而只需保存在CPU内的寄存器中,以使速度大大提高。由于CPU内的寄存器数量是有限的,不可能为某个变量长期占用。因此,一些操作系统对寄存器的使用做了数量的限制。或多或少,或根本不提供,用自动变量来替代。
4.2.4静态存储变量
在编译时分配存储空间的变量称为静态存储变量,其定义形式为在变量定义的前面加上关键字“static”,例如:
static int a=8;
定义的静态存储变量无论是做全程量或是局部变量,其定义和初始化在程序编译时进行。
作为局部变量,调用函数结束时,静态存储变量不消失并且保留原值。
从上述程序看,函数f()被三次调用,由于局部变量x是静态存储变量,它是在编译时分配存储空间,故每次调用函数f()时,变量x不再重新初始化,保留加1后的值,得到上面的输出。
C语言函数的作用域规则的更多相关文章
- 【C语言入门教程】5.2 函数的作用域规则(auto, static)
作用域规则是指代码或数据的有效使用范围.C语言将函数作为独立的代码块,函数之间不能相互访问其内部的代码或数据.函数间数据的传递只能通过接口实现.但是,变量的定义方法可改变函数的作用域规则,可将变量分为 ...
- Python函数的作用域规则和闭包
作用域规则 命名空间是从名称到对象的映射,Python中主要是通过字典实现的,主要有以下几个命名空间: 内置命名空间,包含一些内置函数和内置异常的名称,在Python解释器启动时创建,一直保存到解释器 ...
- 吴裕雄--天生自然C语言开发:作用域规则
#include <stdio.h> int main () { /* 局部变量声明 */ int a, b; int c; /* 实际初始化 */ a = ; b = ; c = a + ...
- C语言-存储类&作用域&生命周期&链接属性
1.概念解析(1)存储类 a.存储类就是存储类型,也就是描述C语言变量在何种地方存储. b.内存有多种管理办法:栈.堆.数据段.bss段..text段......一个变量的存储类属性就是描述这个变量存 ...
- C语言基础知识【作用域规则】
C 作用域规则1.任何一种编程中,作用域是程序中定义的变量所存在的区域,超过该区域变量就不能被访问.C 语言中有三个地方可以声明变量:在函数或块内部的局部变量在所有函数外部的全局变量在形式参数的函数参 ...
- 新手入门C语言第十章:C作用域规则
C 作用域规则任何一种编程中,作用域是程序中定义的变量所存在的区域,超过该区域变量就不能被访问.C 语言中有三个地方可以声明变量: 在函数或块内部的局部变量 在所有函数外部的全局变量 在形式参数的函数 ...
- C语言的作用域规则
作用域规则 程序中名字的作用域,通俗的讲,就是这个名字在程序中的使用范围.在C语言中,作用域的规则相对比较简单,主要分为 全局作用域 和 局部作用域 两种. 一个变量如果定义在函数中,那么这个变量的作 ...
- C语言变量、函数的作用域及变量的存储方式
一.变量的作用域和存储方式 在C语言中每个变量都有两种基本属性:数据类型.数据的存储类别. 数据类型很多人都已熟知,例如:字符型(char).整型(int).浮点型(float)等等.存储类别是指数据 ...
- C语言中变量和函数的作用域和链接属性
C语言中变量和函数的作用域和链接属性 作用域 代码块作用域: 代码块指的是使用"{}"包围起来的部分. 在代码块中定义的变量,代码块之外是不能访问的. 代码块嵌套之后的变量作用域, ...
随机推荐
- HNOI2013 BZOJ3142 数列
尝试用Markdown写一篇博客 3142: [Hnoi2013]数列 Description 小T最近在学着买股票,他得到内部消息:F公司的股票将会疯涨.股票每天的价格已知是正整数,并且由于客观上的 ...
- bzoj 2002 HNOI 2010 弹飞绵羊
Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置 ...
- 模板引擎(smarty)知识点总结三
阔别了几个月,小杨又来分享php知识.话不多说,言归正传,今天继续带来smarty的知识点. -----------------smarty assign append 详解 对于这两个的区别和联系 ...
- 第二节 安装CentOS
Linux 第二节一.安装VNware workstation 10二.安装CentOS 1.root/123456 用户登录[root@localhost ~]# 2.关机 init 0 3.ifc ...
- 在win7下用net命令无法实现对用户的创建(未完成)
============================================================================================= 201307 ...
- 【转】教你开发jQuery插件
阅读目录 基本方法 支持链式调用 让插件接收参数 面向对象的插件开发 关于命名空间 关于变量定义及命名 压缩的好处 工具 GitHub Service Hook 原文:http://www.cnblo ...
- Python random模块sample、randint、shuffle、choice随机函数概念和应用
Python标准库中的random函数,可以生成随机浮点数.整数.字符串,甚至帮助你随机选择列表序 列中的一个元素,打乱一组数据等. random中的一些重要函数的用法: 1 ).random() 返 ...
- 执行查询“BACKUP LOG [XXX] TO DISK = N'F:\\BackData\\事务日至备份\\...”失败,错误如下:“无法执行 BACKUP LOG,因为当前没有数据库备份。 BACKUP LOG 正在异常终止。
执行查询"BACKUP LOG [XXX] TO DISK = N'F:\\BackData\\事务日至备份\\..."失败,错误如下:"无法执行 BACKUP LOG ...
- Fiddler中如何过滤会话、查询会话、保存回话、对比会话
1.Fiddler中如何过滤会话 在抓包时,会捕捉到很多的会话,但是我们只关心特定的接口会话,这个时候我们可以使用过滤功能,来帮助我们从一大堆会话中筛选去我们关心的会话 (1)勾选过滤器选项Filte ...
- SpringMVC 如何在页面中获取到ModelAndView绑定的值
springMVC中通过ModelAndView进行后台与页面的数据交互,那么如何在页面中获取ModelAndView绑定的值呢? 1.在JSP中通过EL表达式进行获取(比较常用) 后台:ModelA ...