C Primer+Plus(十二)(1)

第12章 存储类、链接和内存管理

12.1存储类

存储类,也可称为存储模型,即一个变量,它在内存中是如何存放,生存多久,以及作用范围。先说明几个名词的含义:

12.1.1作用域

作用域描述的是一个变量(标识符)可以在程序哪些区域被使用,包括:代码块作用域、函数原型作用域、文件作用域。

int x;                 //此处x作用域为整个程序文件
main(void)
{
  int functiona(int b);    //此处为函数声明,b只是参数表示,不是特指变量
  int a;                   //a作用域从此处至main函数结束
  for(int i=0;i<a;i++)     //i作用域仅为for循环代码段
   {int m;                 //m作用域从此处至for循环结束   
    functiona(m);
functionb(m); ...; } }
int functiona(int x) //此处x作用域为函数原型,不同于程序开始处的x,程序开始处的x变量此时已被屏蔽 {int a; //a作用域从此处至functiona函数结束,不同于main中a,main中a此时已被屏蔽 ... } //被调函数结束,被屏蔽的x和a解封
  int functionb(int a1){} 

说明,对于上例程序中开头的变量x,在程序functiona和functionb中均是可用的,只是因为functiona中定义了一个同名变量,导致其在functiona中被屏蔽。

12.1.1链接

链接是指什么?粗略看完整章,用自己的理解说明一下:一个变量,除去在程序文件中的作用域之外,还可以在哪里使用?若可以被其他程序文件使用,则称外链接;若可以在本文件内部任何地方使用,则称内链接。而仅具有代码块作用域或函数原型作用域的变量不具备链接性,称为空链接。

int a=5; //具备文件作用域,具备外链接性,称为外链接
static int b=6;   //具备文件作用域,内链接
int main(void)
{...
}

12.1.3存储时期

C变量有两种存储时期:静态存储时期(static storage duration)和自动存储时期(automatic storage duration)。

静态存储时期表示该类变量在程序执行期间将一直存在。具有文件作用域的变量具有静态存储时期特性。

自动存储时期表示该类变量仅在程序运行在其作用域内时存在,一旦程序退出作用域,存储该变量的内存将被释放。代码块作用域和函数原型作用域的变量一般均为自动存储类型。

在上述三个概念介绍后,提出5种存储类型:


 
         
         
         
         
         
         
         
         
         
         
         
         

存储类                        时期                    作用域                     链接                             声明方式

自动         自动       代码块        空         代码块内

寄存器        自动         代码块        空         码块内,使用关键字register

具有外部链接的静态      静态       文件         外部        所有函数之外

具有内部链接的静态  静态         文件         内部        所有函数之外,使用关键字static

空链接的静态     静态       代码块        空         代码块内,使用关键字static


依次介绍:

12.1.4自动存储类型的变量

具有:自动存储时期,代码块作用域,空链接特性。一般情况,在代码块头部或函数头部定义的变量都属于自动存储类型。

int main()
{int a;   //a属于自动存储类
  auto int b;  //也可用auto关键字显式声明自动存储类变量b
  int f1();
  ...
}
int f1(void)
{
   int m;   //正常声明一个自动存储类变量
   auto int n;  //也可通过auto
  ...
}

自动存储时期意味着程序进入该变量所处代码块时候,变量被分配内存空间,当程序结束该代码块时候,自动变量就不存在了,即所占内存被释放。

*对于自动存储类变量,若未被初始赋值,则其值是其所占内存单元里的数值,也就是不可预知的。

12.1.5寄存器存储类变量

当希望变量可被更快速的访问和操作,因为VPU访问寄存器单元肯定比访问内存更快速,则可选用该类型。

声明形式:register int a;通过该声明使得在程序编译到此句时,给变量a分配寄存器(若寄存器不够用,则分配相对更快速的内存单元)。因多数情况下该声明后分配存储区为寄存器,而寄存器的地址是不可读的,则该类变量无法进行&操作,因为取不到地址。

12.1.6具有代码块作用域的静态变量

静态变量是指变量的存储位置固定不动。回想一下,在程序文件头声明定义的变量都是静态变量;另一种静态变量则是具有代码块作用域的静态变量,它的作用域仅限于代码块,同时具备空链接性,但它的生命周期是贯穿从定义初始,到程序结束的。

#include<stido.h>
int main(void)
{
   int i;
   void fs();
   for(i=0;i<2;i++)
     fs();
   return 0;
}
void fs()
{int x=1;
  static y=2;
  printf("%d-%d",x++,y++);
}

上程序在TC3.0下运行结果如下:

1-2

1-3

函数fs体内定义了两个变量,x是明显的自动存储类变量,作用域和生命周期都仅限于每一次调用中的fs,每一次调用fs都会临时给每次的x分配内存空间,并初始化数值1;而y是静态存储类,因其在函数体内定义,其作用域也仅限于函数体,但其在整个程序运行期间(从y被定义至程序结束)都在固定地址存放,并且只有当函数fs被调用时候才可以被使用。

代码块作用域静态存储类变量不能用于函数的参数。

12.1.7具有外部链接的静态变量

该类变量具有文件作用域、静态存储类、外部链接特性。也称为“外部变量”。在程序中所有函数之外定义声明一个变量,则创建了外部变量。

(1)定义声明:是指外部变量的初始创建。

(2)内部引用声明:指在同一文件中,函数在使用该外部变量时候通过关键字extern的引用声明,该声明一般可省略。

(3)外部引用声明:在其他文件中若要使用另一文件内创建的外部变量,则必须显式声明。

------file a---------
int tsa;          //定义声明外部变量tsa
int tsb=1;     //也可定义声明外部变量tsb,并初始化
int main()
{ int i,j;
   ...
}
void f1()
{
   extern int tsa;   //因在同一文件里,该处声明也可以省略
   ....
}
----------------------------
---------file b---------
#include"a.h"        //包含引用声明变量的定义文件
extern int tsb;   //引用声明,必须的,因为该变量的定义不在同一文件中
int main()
{...
}

再看下例:

#include <stdio.h>
int x1;   //定义声明外部变量x1
int main()
{ int x1;   //定义声明自动变量x1,和上述外部变量只是同名
   ....       //在main代码块里,只有自动变量x1起作用
}

*若外部变量定义声明时候未初始赋值,则其初始值为0。并且外部变量只可以用常量表达式来初始化赋值。

例如对于外部变量a:  int a=2*b;   //是非法的,即便变量b事先已被定义

*定义和声明:区别在于系统何时给变量分配存储空间则称为定义。对于引用声明关键词extern的使用,若和外部变量定义语句在同一文件中则可省略;若不在同一文件则该关键字是不可省略的。对于应用声明,还需要注意如下:

int a1=2;  //定义声明一个外部变量a1,并赋值2
int main()
{
   extern int a1;   //正确,但可省略
   extern int a1=3;  //错误,该语句仅是引用声明,而不能赋值;即便理解为定义声明一个外部变量也应该是在所有函数之外进行
   //若忽略上两句
   a1=3;    //正确
...
}

12.1.8具有内部链接的静态变量

该类变量具有:静态存储时期,文件作用域以及内链接特性。在所有函数外部通过关键字static定义声明该类变量。

(1)定义声明:是指外部变量的初始创建。

(2)内部引用声明:指在同一文件中,函数在使用该外部变量时候通过关键字extern进行声明,该声明一般可省略。但该声明不改变内部链接特性。

原文地址:https://www.cnblogs.com/tsembrace/p/3146372.html