C语言的存储类别

发布时间 2023-04-29 21:39:58作者: RenKaixuan

存储类别

概念

  • 对象:硬件中,被存储的每个值都占用一定的物理内存,c语言吧这样的一块内存成为对象
  • 标识符:标识符用来指定特定的对象
  • 存储期:用来描述对象,描述对象在内存中保留了多长时间
  • 作用域、用来描述标识符,描述程序中可以访问标识符的区域
  • 链接:用来描述标识符,c语言有3中链接属性:外部链接、内部链接、无连接
  1. 作用域

    c拥有四种作用域:块作用域、函数作用域、函数原型作用域、文件作用域

    • 块作用域

      块是一对花括号括起来的代码区域,如,整个函数体、任意复合语句

      定义在块中的变量具有块作用域

      可见范围:从定义处含该定义块的末尾

    • 函数作用域

      函数作用域仅用于goto语句的标签

    • 函数原型作用域

      用于函数原型中的形参名

      int mighty(int mouse, double large);
      

      可见范围:从形参定义处到原型声明结束

      这意味着,编译器在处理函数原型中的形参时只关心它的类型,形参名无关紧要。即使有形参名,也不必与函数定义中的形参名相匹配

      注意:边长数组中,形参名有用

      void use_a_VLA(int n, int m, ar[n][m]);
      

      方括号中必须使用在函数原型中已声明的名称

    • 文件作用域

      定义在函数外面的变量,具有文件作用域。

      可见范围:定义处文件末尾

  2. 链接

    c拥有3中链接属性:外部链接、内部链接、无连接

    • 无连接

      无连接变量:块作用域变量、函数原型作用域变量、函数作用域变量

      这些变量只属于定义他们的区域

    • 外部链接

      外部链接变量:文件作用域变量

      外部链接作用域变量简称为全局作用域变量可以在多文件程序中使用

    • 内部链接

      内部链接变量:文件作用域变量

      只能在一个翻译单元中使用

      一个翻译单元:一个源代码文件和它所包含的头文件

  3. 存储期
    c有四种存储期:静态存储期、线程存储期、自动存储期、动态分配存储期

    • 静态存储期

      生存期:在程序的执行期间一直存在。

      变量:文件作用域变量具有静态存储期

      注意:static关键字只表明了该变量是内部链接变量,无论是外部链接变量还是内部链接变量,文件作用域变量都具有静态存储期

    • 线程存储期

      生存期:线程存储期用于并发程序设计,从被声明到线程结束一直存在

      变量:以关键字_Thread_local_声明的变量,此类变量在每个线程中都有私有备份

    • 自动存储期

      生存期:从块的开始处到块的结束,边长数据是从变量定义到块结束

      变量:块作用域变量就具有自动存储期

存储类别

存储类别 存储期 作用域 链接 声明方式
自动 自动 块内
寄存器 自动 块内,使用关键字register
静态外部链接 静态 文件 外部 所有函数外
静态内部链接 静态 文件 内部 所有函数外,使用关键字static
静态无链接 静态 块内,使用关键字static
  1. 自动变量

    • 属性:自动存储期、块作用域、无链接

    • 定义:声明在块、函数头中的任意变量都属于自动存储变量

      int main(void)
      {
         auto int plox;
      }
      
    • 关键字auto是自动变量说明符,块内定义的变量默认为auto类型,为了与c++程序兼容,通常省略auto说明符

    • 块作用域和无链接意味着只有在变量定义的块中才能访问该变量

    • 如果内层块的变量名与外层块中的变量同名,内层块会隐藏外层块的定义

    • 自动化变量不会初始化

  2. 寄存器变量

    • 属性:块作用域、无连接、自动存储期

    • 定义:使用说明符register

      int main(void)
      {
          register int quick;
      }
      
    • 编译器会根据情况衡量register变量,有时会忽略register,此时变量会变成普通的寄存器变量

    • 即使register变量变成了普通自动变量,仍然不能对该变量使用地址运算符

  3. 静态无连接

    • 属性:块作用域、无连接、静态存储器

    • 定义:在块中使用static声明的变量

      #include <stdio.h>
      void trystat(void);
      
      int main(void)
      {
          int count;
          
          for (count = 1; count <= 3; count++)
          {
              printf("Here comes iteration %d:\n", count);
              trystat();
          }
          
          return 0;
      }
      
      void trystat(void)
      {
          int fade = 1;
          static int stay = 1;
          printf("fade = %d and stay = %d\n", fade++, stay++);
      }
      
    • 静态变量stay可访问的范围仍然是trystat函数内,但每次调用后的stay变量值会被保存

  4. 外部链接的静态变量

    • 属性:文件作用域、外部链接、静态存储期

    • 定义:定义在所有函数外面的变量,有时称为外部变量

    • 外部变量可在函数中用关键字extern再次声明。

    • 如果一个源代码文件使用的外部变量定义在另一个源代码文件中,则必须使用extern在该文件中声明变量

      int Errupt; /* 外部变量 */
      extern char Coal; /* 定义在另一个文件中的外部变量 */
      
      int main(void)
      {
          extern int Errupt; /* 可选的声明 */
          ...
      }
      
    • 外部变量若未显式的初始化赋值,外部变量会被初始化为0,数组内容亦是如此

  5. 内部链接的静态变量

    • 属性:文件作用域、静态存储期、内部链接

    • 定义:使用static定义在所有函数外部的变量,也称外部静态变量

      static int svil = 1; // 静态变量,内部链接
      int main(void)
      {
          
      }
      
    • 可视范围:同一文件的任意函数

  6. 存储类别和函数

    • 函数拥有两种存储类别:外部函数(默认)、静态函数

      double gamma(double); /* 函数默认为外部函数 */
      static double beta(int, int); /* 静态函数 */
      extern double delta(double, int);/* 外部函数 */
      
    • 在同一程序的其他源文件中,可以调用gamma和delta,但是不能调用beta

    • 使用static的函数具有文件私有性,可避免名称冲突的问题

    • 通常的做法是:用extern关键字声明定义在其他文件中的函数。
      此篇文章为学习C Primer Plus 第六版的笔记