c语言之函数存储属性,C语言作用域、链接属性和存储类型

作用域

编译器可以确认的4种作用域-代码块作用域、文件作用域、函数作用域和原型作用域,一般来说,标识符(包括变量名和函数名)声明的位置决定它的作用域。

(1)代码块作用域

一对花括号成为一个代码块,任何在代码块开始位置声明的标识符(不包括代码块的函数名)具有代码块作用域。

代码块处于嵌套状态时,声明于内层代码块的标识符的作用域到达该代码块的尾部(包括花括号)便终止。注意:如果内层代码块的某个变量与外层相同,内层会将外层的变量隐藏,即内层代码块无法访问到外层标识符。

(2)文件作用域

任何在所有代码块之外声明的标识符都具有文件作用域,表示从声明之处到源文件结尾都是可以访问的,包括定义的函数名,函数名本身不属于代码块。

(3)原型作用域

原型作用域只适用于函数原型中的参数名。

(4)函数作用域

这种作用域只适用于语句标签,如goto语句。

链接属性

标识符的链接属性决定处理在不同文件中出现的标识符,一共分三种-external(外部),internal(内部)和none(无)。

internal属性的标识符在同一个源文件内所有的声明都指向同一个实体,但不同文件的多个声明则表示不同的实体,比如static声明的变量和函数的链接属性。

external属性的标识符不论声明多少次,位于几个源文件都表示同一个实体,比如extern声明的变量和函数,或者缺省情况下的全局变量。

none属性的标识符,比如代码块中声明的局部变量。

extern和static用于在声明中修改标识符的链接属性:比如为external属性的标识符前加static则会变成internal,注意:非外部链接的变量前加static,将不会改变链接属性,比如局部变量前加static会变成静态局部变量;extern关键字表示可以访问在其他位置(全局变量)定义的这个实体,但需要注意如果一个变量声明于代码内部,extern关键字将使它引用全局变量而不是局部变量。

存储类型

变量的存储类型是指存储变量值的内存类型,变量的存储类型决定变量何时创建,何时销毁以及它的值将保持多久。普通内存、运行时堆栈、硬件寄存器可以存储变量。

凡是在代码块之外声明的变量总是存储在静态内存中,也就是不属于堆栈的内存,这类变量称为静态变量,静态变量在程序运行之前创建,程序运行期间都会存在,程序结束则销毁,他始终保持原有值,除非被赋予其他值。

代码块内部声明的变量的缺省存储类型是自动变量,存储于堆栈中,每次调用时执行到声明变量的代码块时才创建,离开时便销毁。反复调用时,他们的值并不是上次执行的值。变量前加static会变成静态变量,但不会改变其作用域。函数的形参不能声明为静态,因为实参总是在堆栈中传递给函数。

register寄存器变量,表示变量存储在寄存器中而不是内存中,用于自动变量的声明,这并不能保证将变置在寄存器中,甚至也不能保证提高访问速度。这只是对编译器的一个暗示。

使用register变量是有限制的:(1) 不可能得到或计算register 变量的地址; (2) register变量只能在一个块中声明(不可能有全局的或静态的register变量)。然而可以在一个函数中(即在参数表中)使用register变量作为一个形式参数。

自动变量和静态变量的初始化也有差异,静态变量只在程序开始时执行一次,若不显式的初始化,将被初始化为0,每次调用时自动变量的存储位置可能不同,因此没有显式初始化的值。

变量的作用域

静态变量主要是全局变量、静态全局变量、静态局部变量,自动变量分为局部变量,寄存器变量

(1) 全局变量:

全局变量是在所有函数体的外部定义的,程序的所在部分(甚至其它文件中的代码)都可以使用。全局变量不受作用域的影响(也就是说,全局变量的生命期一直到程序的结束)。

(2) 局部变量:

局部变量出现在一个作用域内,它们是局限于一个函数的。

(3) 寄存器变量

寄存器变量是一种局部变量。关键字register告诉编译器“尽可能快地访问这个变量”。加快访问速度取决于现实,但是,正如名字所暗示的那样,这经常是通过在寄存器中放置变量来做到的。这并不能保证将变置在寄存器中,甚至也不能保证提高访问速度。这只是对编译器的一个暗示。

(4) 静态变量

关键字static有一些独特的意义。通常,函数中定义局部变量在函数中作用域结束时消失。当再次调用这个函数时,会重新创建变量的存储空间,其值会被重新初始化。如果想使局部变量的值在程序的整个生命期里仍然存在,我们可以定义函数的局部变量为static(静态的),并给它一个初始化。初始化只在函数第一次调用时执行,函数调用之间变量的值保持不变,这种方式,函数可以“记住”函数调用之间的一些信息片断。这也就是所谓的静态局部变量,具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行结束都一直存在,它和全局变量的区别在于全局变量对所有的函数都是可见的,而静态局部变量只在定义自己的函数体内始终可见。

我们可能奇怪为什么不使用全局变量。static局部变量的优点是在函数范围之外它是不可用的,所以它不可能被轻易改变。这会使错误局部化。

此外同样存在静态全局变量,具有全局作用域,它与全局变量的区别在于如果程序包含多个文件的话,它作用于定义它的文件里,不能作用到其它文件里,即被static关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同名字的静态全局变量,它们也是不同的变量。

从分配内存空间看:全局变量,静态局部变量,静态全局变量都在静态存储区分配空间,而局部变量在栈里分配空间。

注意:在程序中不要使用过多的全局变量,尽量用静态局部变量进行替代。

C语言中的作用域,链接属性和存储类型

作用域 当变量在程序的某个部分被声明的时候,他只有在程序的一定渔区才能被访问,编译器可以确认4种不同类型的作用域:文件作用域,函数作用域,代码块作用域和原型作用域 1.代码块作用域:位于一对花括号之间 ...

C和C指针小记(六)-基本声明、指针声明、typedef 、常量、作用域、链接属性、存储类型、static

1.变量的声明 声明变量的基本形式: 说明符号(一个或者多个) 声明表达式列表 说明符 (specifier) 包含一些关键字,用于描述被声明的标识符的基本类型,它也可用户改变标识符的缺省存储类型和作 ...

关于extern和static关键字引出的一些关于作用域和链接属性和存储类型的问题

在进入正题前我们必须了解一些概念: 标识符:标识符不仅仅代表着变量的名字,main()函数的main也是一个标识符,这点很重要. 存储类型:即变量的存储位置及其生存周期:静态区:分为两块 .date ...

C语言中的作用域、链接属性与存储属性

C语言中的作用域.链接属性与存储属性 一.作用域(scope) 代码块作用域 表示{}之间的区域,下例所示,a可以在不同的代码块里面定义. #include int ma ...

C和指针 3.9作用域、存储类型示例

; extern int b; static int c; int d( int e ) { ; register int b; ; extern int a; ... { int e; int a; ...

7、存储类 & 作用域 & 生命周期 & 链接属性

概念解析 存储类 存储类就是存储类型,也就是描述C语言变量在何种地方存储. 内存有多种管理方法:栈.堆.数据段.bss段..text段······一个变量的存储类属性就是描述这个变量存储在何种内存段中 ...

C语言中变量和函数的作用域和链接属性

C语言中变量和函数的作用域和链接属性 作用域 代码块作用域: 代码块指的是使用"{}"包围起来的部分. 在代码块中定义的变量,代码块之外是不能访问的. 代码块嵌套之后的变量作用域, ...

C++变量的存储类型

C++变量和函数包括两个属性:数据类型和数据的存储类型.存储类型是指数据在内存中存储的方式.变量的存储类型分为四种:自动类型(auto),寄存器类型(register).静态类型(static)外部类 ...

C语言中标识符的作用域、命名空间、链接属性、生命周期、存储类型

Technorati 标签: C,标识符,作用域,命名空间,链接属性,生命周期,存储类型,scope,name space,linkage,storage durations,lifetime 无论学 ...

随机推荐

《BI项目笔记》增量ETL数据抽取的策略及方法

增量抽取 增量抽取只抽取自上次抽取以来数据库中要抽取的表中新增或修改的数据.在ETL使用过程中.增量抽取较全量抽取应用更广.如何捕获变化的数据是增量抽取的关键.对捕获方法一般有两点要求:准确性,能够将 ...

Codeforces Round #292 (Div. 1) B. Drazil and Tiles 拓扑排序

B. Drazil and Tiles 题目连接: http://codeforces.com/contest/516/problem/B Description Drazil created a f ...

简述afinal 框架的基本用法

本文只是对afinal做简单的描述,基本和git上给的文档一样,大神绕道! FinalDB模块本文为涉及到 FinalActivity模块,FinalHttp模块,FinalBitmap模块  代码体 ...

MVC6与Asp.net5

http://www.cnblogs.com/n-pei/p/4263148.html https://blogs.msdn.microsoft.com/scottgu/2015/04/30/asp- ...

Python基础之 urllib模块urlopen()与urlretrieve()的使用方法详解。

Python urllib模块urlopen()与urlretrieve()的使用方法详解   1.urlopen()方法urllib.urlopen(url[, data[, proxies]]) ...

[WCF]WCF起航

解决方案概览: Client:windows 控制台应用程序. WcfService1: windows 服务应用程序. WCFWebTest:asp.net 空web应用程序. 变量程序命名.结构可 ...

Python 索引迭代

1.使用enumerate函数 L = ['Adam', 'Lisa', 'Bart', 'Paul'] for index, name in enumerate(L):     print inde ...

LVS简介及使用

一.LVS是什么? LVS的英文全称是Linux Virtual Server,即Linux虚拟服务器.它是我们国家的章文嵩博士的一个开源项目.在linux内存2.6中,它已经成为内核的一部分,在此之 ...

Bzoj2534:后缀自动机 主席树启发式合并

国际惯例的题面:考虑我们求解出字符串uvu第一个u的右端点为i,第二个u的右端点为j,我们需要满足什么性质?显然j>i+L,因为我们选择的串不能是空串.另外考虑i和j的最长公共前缀(也就是说其p ...

小程序文件上传uploadFile

前台代码: bindPhoto(e) { var that = this; wx.chooseImage({ count: 1, sizeType: ['original','compressed'] ...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值