首先介绍三个概念:

(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. INFO: Font Metrics and the Use of Negative lfHeight

    INFO: Font Metrics and the Use of Negative lfHeight  Print  Email   Article translations  Article ID ...

  2. 【涨姿势】Prince2和PMP的区别,大多数人都没搞清楚!

    项目管理领域有2个流行的知识体系:      ☑ 一个是美国项目管理协会(PMI)开发的“项目管理知识体系(PMBOK,Project Management Body of Knowledge)”,目 ...

  3. Fatal error: Can't use function return value in write context

    这个的出错原因很简单,先贴出错代码: <?php $contact = array("id"=>1, "姓名"=>"老高" ...

  4. 11.Spring——JDBC框架

    1.DBC 框架概述 2.Spring JDBC 示例 3.Spring 中 SQL 的存储过程 1.DBC 框架概述 在使用普通的 JDBC 数据库时,就会很麻烦的写不必要的代码来处理异常,打开和关 ...

  5. HBase 负载均衡

    HBase 可以根据当前集群的负载以region为单位进行rebalance.在HMaster中,后台会起一个线程定期检查是否需要进行rebalance,线程叫做BalancerChore.线程每隔  ...

  6. 从零开始导入gradle项目

    需要jdk1.8,idea17以上,电脑安装gradle(配置环境变量,与配置java类似),用git的push命令下项目,开始操作 gradle配置本地仓库位置:添加环境变量GRADLE_USER_ ...

  7. Redis(三)Redis基本命令操作与API

    一Redis 连接 Redis 连接命令主要是用于连接 redis 服务. 实例 以下实例演示了客户端如何通过密码验证连接到 redis 服务,并检测服务是否在运行: redis 127.0.0.1: ...

  8. [翻译] M13BadgeView

    M13BadgeView M13BadgeView is a customizable badge view for iOS applications. The badge is built to b ...

  9. jenkins + k8s + lnp

    前提条件: K8S 已部署好,traefik也部署完成 K8S 集群上都挂载NFS盘,防止jenkins挂掉后配置消失 基础镜像使用 lnp,PHP 5.6.31  nginx/1.8.1  基础镜像 ...

  10. FFI (语言交互接口(Foreign Function Interface))

    FFI(Foreign Function Interface)是用来与其它语言交互的接口, 在有些语言里面称为语言绑定(language bindings), Java 里面一般称为 JNI(Java ...