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语言作用域、链接属性和存储类型的更多相关文章
- C语言中的作用域,链接属性和存储类型
作用域 当变量在程序的某个部分被声明的时候,他只有在程序的一定渔区才能被访问,编译器可以确认4种不同类型的作用域:文件作用域,函数作用域,代码块作用域和原型作用域 1.代码块作用域:位于一对花括号之间 ...
- C和C指针小记(六)-基本声明、指针声明、typedef 、常量、作用域、链接属性、存储类型、static
1.变量的声明 声明变量的基本形式: 说明符号(一个或者多个) 声明表达式列表 说明符 (specifier) 包含一些关键字,用于描述被声明的标识符的基本类型,它也可用户改变标识符的缺省存储类型和作 ...
- 关于extern和static关键字引出的一些关于作用域和链接属性和存储类型的问题
在进入正题前我们必须了解一些概念: 标识符:标识符不仅仅代表着变量的名字,main()函数的main也是一个标识符,这点很重要. 存储类型:即变量的存储位置及其生存周期:静态区:分为两块 .date ...
- C语言中的作用域、链接属性与存储属性
C语言中的作用域.链接属性与存储属性 一.作用域(scope) 代码块作用域 表示{}之间的区域,下例所示,a可以在不同的代码块里面定义. #include<stdio.h> 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 无论学 ...
随机推荐
- 8-5接口测试用例设计与编写2 rest-assured
rest-assured 简约的接口测试DSL 支持xml json的结构化解析 支持xpath jsonpath gpath等多种解析方式 对Spring的支持比较前面 底层是httpclient ...
- kudu安装过程中可能出现的问题
kudu安装过成中可能出现的问题 1.给用户添加sudo权限的时候报错 sudo: /etc/sudoers is world writable 解决方式:pkexec chmod /etc/sudo ...
- [NOI2007]生成树计数环形版
NOI2007这道题人类进化更完全之后出现了新的做法 毕姥爷题解: 于是毕姥爷出了一道环形版的这题(test0814),让我们写这个做法 环形的情况下,k=5的时候是162阶递推. 求这个递推可以用B ...
- mysql索引原理深度解析
mysql索引原理深度解析 一.总结 一句话总结: mysql索引是b+树,因为b+树在范围查找.节点查找等方面优化 hash索引,完全平衡二叉树,b树等 1.数据库中最常见的慢查询优化方式是什么? ...
- csdn自动生成目录索引、插入代码片快捷键
文章目录 自动生成目录索引 插入代码片 自动生成目录索引 文章开头加入 @[TOC](目录描述) 目录描述可不写 插入代码片 cmd/ctrl + shift + k
- Post Office IOI 2000 /// 区间DP oj24077
题目大意: 给定n个村庄的坐标,两个村庄之间的距离是其坐标之差的绝对值 最多能选m个村庄设立邮局,求设立邮局的地点使得各村庄与邮局距离总和最小 一, 所有的村庄看做在一条直线上 考虑三个因素:i 当前 ...
- C# 中的三个高级参数 ref
今天在浏览博文时,看到这篇文章:C#中的ref 传进出的到底是什么 ? 在传对象时使用ref的疑问 引用类型就传的就是地址,值类型传的就是值,可是还仍有那么多人迷惑,网上虽然流传着很多ref 的相关文 ...
- netty DelimiterBasedFrameDecoder
netty server EchoServer package com.zhaowb.netty.ch5_1; import io.netty.bootstrap.ServerBootstrap; i ...
- Leetcode148. Sort List排序链表
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序. 示例 1: 输入: 4->2->1->3 输出: 1->2->3->4 示例 2: 输入 ...
- 【BZOJ4916】神犇与蒟蒻
题面 Description 很久很久以前,有一只神犇叫yzy; 很久很久之后,有一只蒟蒻叫lty; Input 请你读入一个整数N;\(1<=N<=10^9\),A.B模\(10^9+7 ...