C 中的存储类别是什么?

2024 年 8 月 28 日 | 阅读 6 分钟

我们在几乎所有程序中都声明变量。并非所有变量都具有相同的特性。变量的声明、在程序不同部分的可访问性因变量而异,具体取决于变量的声明位置。“存储类别” 只是用于确定变量的一些重要特性,例如:

  1. 可见性
  2. 内存位置
  3. 如果未初始化,则初始值
  4. 生命周期

本文解释了 C 语言中的存储类别是什么。因此,C 编程语言中有 4 种不同的存储类别:

  1. 自动 (auto)
  2. 外部 (extern)
  3. 静态 (static)
  4. 寄存器 (register)

这里,括号中的词是该特定存储类别的关键字。下面是一个我们将通过示例进一步探讨的简单表格:

存储类别关键字变量存储在哪里变量的初始值范围生命周期
autoStack垃圾值在使用的代码块内代码块结束时
extern数据段0全局(跨多个文件活动)直到程序结束
static数据段0在代码块内直到程序结束
registerCPU 寄存器垃圾值在代码块内代码块结束时

每个变量的四个特性

  1. 变量的作用域: 变量的作用域是指变量的值可以被访问的程序部分。
  2. 变量的生命周期: 这决定了变量在整个程序中会存活多久。
  3. 初始值: 当我们只声明一个变量而没有给它任何值时,编译器赋予它的值。
  4. 存储: 确定变量存储在哪里。

说明

1. "自动"存储类别

这是所有变量的默认存储类别。因此,我们在声明中不会单独提及它。这些变量只能在声明它们的代码块内访问。如果存在嵌套块,则可以在嵌套块内访问这些变量。

如果我们想在代码块外部访问变量,那么我们使用指向该变量的指针并通过 *pointer 访问。

我们使用关键字“auto”来访问自动变量。如果未初始化,编译器会给变量一个垃圾值,我们可以在程序稍后修改它。

快速概览

存储: 处理器中的堆栈

生命周期: 在该特定块中

作用域: 允许在该特定块中

初始值: 垃圾值

语法

示例程序

输出

num=500
num=300
num=100

理解

程序中的不同代码块以不同的块区分,以使其易于理解。自动变量赋给的值的作用域仅限于该特定块。因此,在执行时,内部代码块首先打印 num 的值为 500。之后,外部代码块打印 num 的值为 300,然后执行最外层的代码块,因为值为 100。

2. "外部"存储类别

简单来说,extern 变量是一个全局变量。无论它在哪里声明(在不同的代码块中,也在函数声明中),它都可以在程序中的任何位置访问。已初始化的值可以在程序中的任何地方修改。我们所要做的就是在声明中将“extern”关键字放在变量前面。基本上,extern 变量的值在程序开始时初始化,并在程序其他地方使用。使用 extern 关键字可以扩展该变量的可见性和生命周期。

目的: 使用此外部变量的主要目的是它们可以在构成大型程序的两个不同文件之间访问,并且具有很高的可读性而没有歧义。

  • 当我们想在函数声明或定义中声明一个 extern 变量时,我们不需要手动使用 extern 关键字,因为它在程序中具有可见性,所以是隐式获取的。

快速概览

存储: 在数据段(处理器)中

生命周期: 直到程序结束

作用域: 全局(在多个文件中活动)

初始值: 零 (0)

语法

示例程序

输出

0

理解: extern 变量在 main 函数上方声明。它现在在程序中的任何地方都是可用的——全局的。它没有被赋予任何值——未初始化。现在,我们打印变量只是为了查看编译器赋予的初始值 0。

输出

num = 7

全局变量和 extern 变量有什么区别?

  • 简单地说,当我们使用 extern 关键字时,它不会创建一个将在全局范围内可用的变量。相反,我们正在访问在其他模块中定义的全局变量。
  • 通过在变量前使用 extern 关键字,我们告诉编译器该变量在另一个模块中定义。不要为此分配单独的存储空间,只需在该模块中查找并访问它即可在此程序中使用。

3. "静态"存储类别

静态变量以其保留特性而闻名。即使在超出作用域后,它也会一直存储到程序结束。它会保留其存储中的最后修改值。我们不需要一直声明它来使用它,而是对其进行重新声明。

快速概览

存储: 在数据段(处理器)中

生命周期: 直到程序结束

作用域: 在局部块内

初始值: 零 (0)

语法

示例程序

输出

6  11

理解

变量 num 在函数声明块中被声明为静态变量,并赋予值 1。因此,该变量的作用域仅限于该块。但是,正如你所观察到的,在第一次函数调用时,值与 5 相加,变成 1+5 = 6。它被打印出来,在第二次函数调用时,num 的值被取为 6,因此变成 6+5 = 11。它不是取 1,因为静态变量会保留最后修改的值。

4. "寄存器"存储类别

这些变量在功能上与自动变量相同。唯一的区别在于存储。自动变量存储在堆栈中,而寄存器变量存储在微处理器的寄存器中(如果可用)。这使得访问和处理这些变量比自动变量快得多。

注意事项

  • 如果当时微处理器中没有可用的空闲寄存器,那么它们就只存储在普通内存中。
  • 程序中经常需要的变量被声明为寄存器存储类别变量,以减少变量的运行时间。
  • 我们无法使用指针获取寄存器变量的地址。

快速概览

存储: 微处理器中的寄存器类别

生命周期: 在该特定块中

作用域: 允许在该特定块中

初始值: 垃圾值

语法

示例程序

输出

Compiler Error

理解

该变量的地址将不在处理器的堆栈中。它将在寄存器类别中可用。因此,编译器将无法访问其地址 &num,从而导致错误。