首先介绍三个概念:

(1)作用域:作用域描述了程序中可以访问一个标识符的一个或多个区域。

一共有三种作用域:代码块作用域、函数原型作用域和文件作用域

a.代码块作用域:一个代码块是包含在开始花括号和对应结束花括号之间的一段代码,在代码块内定义的变量具有代码块作用域,从该变量定义的地方到包含该定义的代码块的结尾该变量均可见。

传统上,具有代码块作用域的变量都必须在代码块的开始处进行声明,c99放宽了这一规则,允许在代码块的任何位置声明变量,譬如说for循环的控制部分,类似的还有while循环、do while循环等。

以for循环为例:

for(int i = 0; i < 100; i++) ;

 对于变量i来说,只在for循环中可见,离开了for循环,i就不可见了。

b.函数原型作用域:适用于函数原型中使用的变量名。函数原型作用域从变量定义处一直到原型声明的末尾。

int test(int a, int b);

以上述声明为例,变量a、b的作用域只有上面这一行声明。这意味着,在处理一个函数原型的参数时,它所关心的只是参数的类型,使用什么名字是无关紧要的。

c.文件作用域:一个在所有函数之外定义的变量具有文件作用域,具有文件作用域的变量从它定义处到包含该定义的文件结尾处都是可见的。文件作用域变量也被称为全局变量。

(2)链接

一个C变量具有下列链接之一:外部链接、内部链接或空链接

a.空链接:具有代码块作用域或函数原型作用域的变量具有空链接,意味着它们是由其定义所在的代码块或者函数原型所私有的。

b.外部链接、内部链接:具有文件作用域的变量可能有内部链接或者外部链接。一个具有外部链接的变量可以在一个多文件程序的任何地方使用,一个具有内部链接的变量可以在一个文件的任何地方使用。

如何区分外部链接和内部链接呢?声明前面有无static。

(3)存储时期

一个C变量具有以下两种存储时期之一:静态存储时期和自动存储时期

静态存储时期:如果一个变量具有静态存储时期,它在程序执行期间将一直存在,具有文件作用域的变量具有静态存储时期;

自动存储时期:具有代码块作用域的变量一般具有自动存储时期。在程序进入定义这些变量的代码块时,会为这些变量分配内存,当推出这个代码块时,分配的内存将被释放。

  

下面介绍几种变量:

(1)自动变量

属于自动存储类的变量具有自动存储时期、代码块作用域和空链接,默认情况下,在代码块和函数的头部定义的任何变量都属于自动变量。然而,也可以像下面所示显式地使用关键字auto

int main()
{
auto int a;
}

为了有意覆盖一个外部函数定义时,或者为了表明不能将变量改变成其他存储类的时候,可以使用auto。

自动变量的初始化:除非显式地初始化自动变量,否则它不会被自动初始化,如果未初始化,它的初值是先前占用分配给它的空间的任意值。

(2)寄存器变量

通常的变量被存储在计算机内存中,如果幸运的话可以被存储在CPU寄存器中,可以比普通变量更快地被访问和操作。因为寄存器变量多是被存在一个寄存器中而非内存中,因此无法获得寄存器变量的地址,和自动变量一样,它们都具有代码块作用域、空链接以及自动存储时期。

使用关键字register可以声明寄存器变量,但是即使声明了,变量也不一定会被存在寄存器中。

(3)具有代码块作用域的静态变量

这种变量是具有代码块作用域,兼具静态存储的局部变量。这些变量和自动变量具有相同的作用域,但当包含这些变量的函数完成工作时,它们并不消失。这些变量具有代码块作用域,空链接,但是却有静态存储时期,从一次函数调用到下一次调用,计算机都记录着它们的值,这样的变量通过存储类说明符static在代码块内声明创建。

(4)具有外部链接的静态变量

具有外部链接的静态变量具有文件作用域、外部链接和静态存储时期。这一变量被称为外部变量。把变量的定义声明放在所有函数之外,即创建了一个外部变量。如果其他文件使用该外部变量,则需要extern关键字来再次声明它。

外部变量可以被显式地初始化,但是不同于自动变量,如果不对外部变量进行初始化,它们会被赋值为0。外部变量只可以用常量表达式来初始化文件作用域变量。

具有extern关键字是一个引用声明而非定义声明,引用声明不会分配空间。

(5)具有内部链接的静态变量

这种存储类的变量具有静态存储时期、文件作用域以及内部连击,通过使用存储类说明符static在所有函数外部进行定义来创建一个这样的变量。

下面是两个类型限定词:const和volatile

(1)类型限定词const:如果变量声明中带有关键词const,则不能通过赋值、增量或减量运算来改变该变量的值,只可以通过初始化进行赋值

指针使用const有以下两种情况:

const float *pf //pf指向一个常量浮点数值,但是pf本身的值可以改变,譬如说,它可以指向另外一个const值

const * float pt; //pt是一个常量指针,它必须指向同一个地址,但所指向的值可以改变

const float * const ptr; //ptr必须总是指向同一个位置,并且它指位置存储的值也不能改变

这种新关键字的一种常见用法是声明作为函数形式参数的指针,这样指针只是让函数访问值。

如果在文件之间使用const数据,可以使用两个策略:

a.遵循外部变量的惯用规则:在一个文件中进行声明,在其他文件中进行引用声明(关键字extern)

b.将常量放在一个include文件中,譬如说constant.h。而且还必须是静态外部存储类:如果不使用关键字static,在多个文件中都包含头文件,导致每个文件都有同一标识符的定义声明(有些编译器不允许这样做)。

(2)类型限定词volatile:

限定词volatile告诉编译器该变量除了可被程序修改以外还可被其他代理改变,典型地,它被用于硬件地址和其他并行程序共享的数据。

存储类、链接和内存管理(c prime plus)的更多相关文章

  1. 《C prime plus (第五版)》 ---第12章 存储类.链接和内存管理

    12-1:存储类: 1.作用域: 代码块作用域,函数原型作用域和文件作用域. 2.链接:分为外部链接,内部链接和空链接.代码块作用域和函数原型作用域都是空连接,意味着是私有的.而文件作用域的变量可能是 ...

  2. C Primer Plus--C存储类、链接和内存管理之存储类(storage class)

    目录 存储类 作用域 链接 存储时期 自动变量 寄存器变量 具有代码块作用域的静态变量 具有外部链接的静态变量 extern关键字 具有内部链接的静态变量 多文件 存储类 C为变量提供了5种不同的存储 ...

  3. C语言中存储类别、链接与内存管理

      第12章 存储类别.链接和内存管理 通过内存管理系统指定变量的作用域和生命周期,实现对程序的控制.合理使用内存是程序设计的一个要点. 12.1 存储类别 C提供了多种不同的模型和存储类别,在内存中 ...

  4. 【C语言学习笔记】存储类、链接和内存管理

    因为对内存管理部分一直没有很清楚的思路,所以一直在找资料想系统看一下这部分的内容.在C primer plus里看到了这一章,虽然大多都是心知肚明的东西,但是还是很多概念性系统性的东西让我眼前一亮,把 ...

  5. C Primer Plus--C存储类、链接和内存管理之动态分配内存及类型限定词

    目录 存储类说明符 存储类和函数 动态分配内存 malloc函数 free函数 calloc函数 动态分配内存的缺点 C类型限定关键字 constant定义全局常量 volatile关键字 restr ...

  6. C Primer Plus之存储类、链接和内存管理

    存储时期即生存周期——变量在内存中保留的时间 变量的作用域和链接一起表明程序的哪些部分可以通过变量名来使用该变量. 注意:生存期和作用域是两个不同的概念. 作用域    作用域描述了程序中可以访问一个 ...

  7. C中存储类、链接和内存管理

    在C语言中,有5种不同的存储类型,即存储类.在介绍存储类之前,需要首先简单介绍几个术语.如下: 作用域:描述程序中可以访问一个标识符的一个或多个区域.一个C变量的作用域可以是代码块作用域.函数原型作用 ...

  8. 【C语言学习】《C Primer Plus》第12章 存储类、链接和内存管理

    学习总结 1.作用域可分为代码块作用域.函数原型作用域或者文件作用域. 代码块作用域例子: { for(int i=0;i<10;i++){  //C99允许 …  //i的作用域 } ... ...

  9. CPrimer Plus第12章 存储类、链接和内存管理随笔

    被static修饰的属于内部链接,不可被外部程序文件所使用一般而言,全局变量(文件作用域变量)具有静态存储期,局部变量(代码块作用域变量)具有自动存储期寄存器变量不能使用地址运算符因为被static修 ...

随机推荐

  1. is_palindrome 回文递归

    # coding=utf-8def is_palindrome(n,start,end): if start>end: return 1 else: return is_palindrome(n ...

  2. 【日常记录】【unity3d】 2D跳跃过快导致角色某帧陷入地面

    如果角色运动过快会导致嵌入地面再反弹出来 : 可以使用更高质量的检测方式 "Continuous" :就可以解决这个问题

  3. SSH安全

    新建用户,设置密码 useradd eason passwd eason 不允许root直接登陆 修改配置文件 vi /etc/ssh/sshd_config 禁止root登录 查找“#PermitR ...

  4. 使用 Azure CLI 管理 Azure 虚拟网络和 Linux 虚拟机

    Azure 虚拟机使用 Azure 网络进行内部和外部网络通信. 本教程将指导读者部署两个虚拟机,并为这些 VM 配置 Azure 网络. 本教程中的示例假设 VM 将要托管包含数据库后端的 Web ...

  5. docker如何创建支持SSH服务的镜像

    一般情况下,Linux系统管理员通过SSH服务来管理操作系统,但Docker的很多镜像是不带SSH服务的,那么我们怎样才能管理操作系统呢?在第一部分中我们介绍了一些进入容器的办法,比如用attach. ...

  6. 简单解析Spring核心IOC容器原理

    将大体流程解析了一边,具体可以看源代码一个方法一个方法的跟下 XmlBeanFactory的功能是建立在DefaultListableBeanFactory这个基本容器的基础上的,并在这个基本容器的基 ...

  7. 0. 跟踪标记 (Trace Flag) 简介

    一. 什么是跟踪标记 SQL Server 跟踪标记(Trace Flag),像是一个开关,可用来自定义SQL Server的某种行为或特性,在性能诊断,系统调试等方面较为常用.比如:开启1204或1 ...

  8. 使用CoreData [3]

    使用CoreData [3] 此篇幅介绍CoreData如何升级版本防止崩溃 把你之前创建的实体文件全部删除掉,把沙盒中的数据库文件删除掉,实体只保持一个,然后重新创建出实体文件. - (BOOL)a ...

  9. windows下安装Mysql(图文详解)

      博客园 | 首页 | 新随笔 | 联系 | 订阅 | 管理 mysql安装过程及注意事项: 1.1. 下载: 我下载的是64位系统的zip包: 下载地址:https://dev.mysql.com ...

  10. 铁乐学python_Day38_多进程和multiprocess模块1

    铁乐学python_Day38_多进程和multiprocess模块1 [进程] 运行中的程序就是一个进程. 所有的进程都是通过它的父进程来创建的. 因此,运行起来的python程序也是一个进程,那么 ...