C 中的存储类:自动、外部、静态、寄存器(示例)

⚡ 智能摘要

C 语言中的存储类定义了每个变量的作用域、生命周期、默认值和内存位置,使用四个说明符——auto、register、static 和 extern——来控制数据在执行期间的存储位置和生存时间。

  • 🗂️ 四种存储类别: C 语言提供了 auto、register、static 和 extern 等变量说明符来描述每个变量。
  • 🏠 自动: 默认的局部类,被限制在其代码块内,并且在赋值之前保存一个垃圾值。
  • 注册: 请求 CPU 寄存器存储空间,以便更快地访问常用变量,例如计数器。
  • ♻️ 静态的: 在函数调用之间保留变量值,首次使用时默认值为零。
  • 🌐 外部的: 在多个源文件中共享全局变量或函数,而无需重新定义。
  • 📊 适用范围和使用寿命: 每个类都会设定变量的可见范围和存在时间。

C 中的存储类

C 中的存储类别是什么?

存储类表示变量的可见性和位置。它告诉我们可以从代码的哪一部分访问变量。C 中的存储类用于描述以下内容:

  • 变量范围。
  • 变量的存储位置。
  • 变量的初始化值。
  • 变量的生命周期。
  • 谁可以访问变量?

因此,存储类用于表示有关变量的信息。

注意:变量不仅与……相关联 数据类型,它的价值也是一个存储类别。

C 中存储类别的类型有哪些?

标准存储类别共有四种。下表表示了 C 中的存储类别。

存储类 目的
汽车 它是一个默认的存储类。
外部 它是一个全局变量。
静止 它是一个局部变量,即使控制权转移到函数调用也能够返回一个值。
寄存器 它是一个存储在寄存器内的变量。

C 语言中的自动存储类

使用自动存储类定义的变量称为局部变量。Auto 代表自动存储类。如果没有明确指定,变量默认为自动存储类。

自动变量的作用域仅限于特定块。一旦控制权离开该块,访问权就会被破坏。这意味着只有声明自动变量的块才能访问它。

关键字 auto 用于定义自动存储类。默认情况下,自动变量包含垃圾值。

Example, auto int age;

下面的程序定义了一个具有两个局部变量的函数

int add(void) {
   int a=13;
   auto int b=48;
return a+b;}

我们采用另一个程序,它显示每个块代码中彼此独立的自动变量的范围级别“可见性级别”:

#include <stdio.h>
int main( )
{
  auto int j = 1;
  {
    auto int j= 2;
    {
      auto int j = 3;
      printf ( " %d ", j);
    }
    printf ( "\t %d ",j);
  }
  printf( "%d\n", j);}

输出:

 3 2 1

C 中的外部存储类

Extern 代表外部存储类。当我们有在两个或多个文件之间共享的全局函数或变量时,使用 Extern 存储类。

关键字 extern 用于在另一个文件中声明全局变量或函数,以提供对原始文件中已定义的变量或函数的引用。

使用 extern 关键字定义的变量称为全局变量。这些变量在整个程序中都可以访问。请注意,extern 变量无法初始化,因为它已经在原始文件中定义。

Example, extern void display();

第一个文件:main.c

#include <stdio.h>
extern i;
main() {
   printf("value of the external integer is = %d\n", i);
   return 0;}

第二个文件:original.c

#include <stdio.h>
i=48;

结果:

 value of the external integer is = 48

为了编译并运行上述代码,请按照以下步骤操作

步骤1)创建新项目,

  • 选择控制台应用程序
  • 点击前往

创建新项目 Code 吹氣梢

步骤 2)选择 C,然后单击“下一步”。

选择 C ​​语言

步骤 3)单击下一步

点击下一步

步骤 4)输入详细信息,然后单击“下一步”。

输入项目详情

步骤 5)点击“完成”

点击完成

步骤 6)将前面程序中所示的主要代码放入 main.c 文件中并保存。

在 main.c 中添加代码

步骤 7)创建一个新的 C 文件 [文件 -> 新建 -> 空文件],保存(为 original.c),然后单击对话框中的“确定”将其添加到当前项目中。

创建 original.c 文件

步骤 8)将前面示例中显示的 original.c 文件中的 C 代码(不包括 main() 函数)放入并保存。

将代码添加到 original.c

步骤 9)构建并运行项目。结果如下图所示。

程序输出

C 语言中的静态存储类

静态变量在函数/文件中用作局部静态变量。它们也可以用作 全局变量

  • 静态局部变量是在函数调用或块之间保留和存储其值的局部变量,并且仅对定义它的函数或块可见。
  • 静态全局变量是指仅在声明它的文件中可见的全局变量。
Example: static int count = 10;

请记住,静态变量具有默认初始值零,并且在其生命周期内仅初始化一次。

#include <stdio.h> /* function declaration */
void next(void);
static int counter = 7; /* global variable */
main() {
 while(counter<10) {
      next();
      counter++;   }
return 0;}
void next( void ) {    /* function definition */
   static int iteration = 13; /* local static variable */
   iteration ++;
   printf("iteration=%d and counter= %d\n", iteration, counter);}

结果:

iteration=14 and counter= 7
iteration=15 and counter= 8
iteration=16 and counter= 9

全局变量可在整个文件中访问,而静态变量只能在代码的特定部分访问。

静态变量的生命周期是整个程序代码。使用 static 关键字声明或初始化的变量始终包含零作为默认值。

C 语言中的寄存器存储类

当你想将函数或块内的局部变量存储在 CPU 寄存器中时,可以使用寄存器存储类,而不是 内存 以便快速访问这些变量。例如,“计数器”是存储在寄存器中的一个很好的候选。

Example: register int age;

关键字 register 用于声明寄存器存储类。使用寄存器存储类声明的变量在整个程序运行期间都保持生命周期。

它类似于自动存储类。变量仅限于特定块。唯一的区别是使用寄存器存储类声明的变量存储在 CPU 寄存器中,而不是内存中。寄存器的访问速度比主内存更快。

使用寄存器存储类型声明的变量没有默认值。这些变量通常在程序开始时声明。

#include <stdio.h> /* function declaration */
main() {
{register int  weight;
int *ptr=&weight ;/*it produces an error when the compilation occurs ,we cannot get a memory location when dealing with CPU register*/}
}

输出:

error: address of register variable 'weight' requested

下表总结了 C 编程中常用的每种存储类的主要特性

存储类 声明 存放 默认初始值 适用范围 终身版
汽车 在函数/块内 内存 变幻莫测 在函数/块内 在函数/块内
寄存器 在函数/块内 CPU 寄存器 垃圾 在函数/块内 在函数/块内
外部 所有功能之外 内存 整个文件以及将变量声明为 extern 的其他文件 程序运行时
静态(本地) 在函数/块内 内存 在函数/块内 程序运行时
静态(全局) 所有功能之外 内存 全球 程序运行时

常见问题

作用域决定了变量在代码中的可见范围,而生命周期决定了变量在内存中保留的时间长短。一个变量可以具有块级作用域,但生命周期却可以覆盖整个程序。

两者都创建块级局部变量,但 auto 会将它们保存在内存中(默认值为垃圾数据),而 register 则请求更快的 CPU 寄存器存储,并禁止获取变量地址。

不,`register` 只是一个请求;如果没有空闲寄存器,编译器可能会忽略它。现代编译器会自动优化寄存器的使用,因此现在很少需要使用 `register` 关键字。

静态变量和外部变量存在于整个程序中初始化为零的内存段中,因此它们的初始值都为零。自动变量会重用栈内存,保持其值不变。ping 无论留下了什么价值。

extern 声明仅用于声明变量已在其他地方定义,不能进行初始化。真正的定义(位于另一个文件中)会分配存储空间,而链接则将所有引用连接到该定义。

差不多,但不完全是。 C++ 弃用了 register 关键字,并将 auto 重新用于类型推断。static 和 extern 的行为类似。 C++ 添加 thread_local 和 class-member 存储规则。

是的。人工智能助手会描述 auto、register、static 和 extern 等类型,建议每个变量的正确说明符,并标记诸如获取寄存器变量地址之类的误用行为。

GitHub 副驾驶 自动补全静态计数器、跨文件的 extern 声明和寄存器提示,并在您键入时内联解释作用域和生命周期。

总结一下这篇文章: