C中的存储类用于确定变量的生存期、可见性、内存位置和初始值。C语言有四种存储类:

  • 自动(Automatic)
  • 外部(External)
  • 静态(Static)
  • 寄存器(Register)
存储类存储位置默认值作用域生命周期
autoRAM未初始化值局部函数内部
externRAM0全局整个主程序的结束前,可以在程序中的任何地方声明
staticRAM0局部整个主程序的结束前,保留在多次函数调用之间的值
register寄存器未初始化值局部函数内部

自动(Automatic)

  • 自动变量在运行时自动分配内存。
  • 自动变量的可见性仅限于定义它们的块。
  • 自动变量的作用域仅限于定义它们的块。
  • 自动变量默认情况下被初始化为垃圾值。
  • 分配给自动变量的内存在退出块时被释放。
  • 定义自动变量的关键字是auto
  • 在C中,默认情况下,每个局部变量都是自动变量。

示例 1

#include <stdio.h>

int main() {
    int a; // 自动变量
    char b;
    float c;
  
    printf("%d %c %f", a, b, c); // 打印自动变量a、b和c的初始默认值
  
    return 0;
}

输出:

garbage garbage garbage

示例 2

#include <stdio.h>

int main() {
    int a = 10, i;
  
    printf("%d ", ++a);
  
    {
        int a = 20;
      
        for (i = 0; i < 3; i++) {
            printf("%d ", a); // 由于a是局部值,因此将打印20三次
        }
    }
  
    printf("%d ", a); // 由于a = 20的作用域已结束,将打印11
  
    return 0;
}

输出:

11 20 20 20 11

静态(Static)

  • 用static关键字定义的变量可以在多个函数调用之间保持其值不变。
  • 静态局部变量只对定义它们的函数或块可见。
  • 同一个静态变量可以声明多次,但只能初始化一次。
  • 静态整型变量的默认初始值为0,否则为null。
  • 静态全局变量的可见性仅限于声明它的文件。
  • 定义静态变量的关键字是static。

示例 1

#include <stdio.h>

static char c;
static int i;
static float f;
static char s[100];

void main() {
    printf("%d %d %f %s", c, i, f, s); // 打印变量c、i和f的初始默认值
}

输出:

0 0 0.000000 (null)

示例 2

#include <stdio.h>

void sum() {
    static int a = 10;
    static int b = 24;
  
    printf("%d %d \n", a, b);
  
    a++;
    b++;
}

void main() {
    int i;
  
    for (i = 0; i < 3; i++) {
        sum(); // 静态变量在多次函数调用之间保持其值
    }
}

输出:

10 24
11 25
12 26

寄存器(Register)

  • 用register关键字定义的变量根据CPU寄存器中剩余的内存大小进行分配。
  • 无法对寄存器变量进行取地址操作,即无法使用&运算符获取寄存器变量的地址。
  • 寄存器变量的访问时间比自动变量快。
  • 寄存器局部变量的默认初始值为0。
  • 用register关键字定义的变量应存储在CPU寄存器中,但具体是否存储在寄存器中取决于编译器。
  • 可以将指针存储到寄存器中,即寄存器可以存储变量的地址。
  • 无法将静态变量存储到寄存器中,因为同一个变量不能使用多个存储类说明符。

示例 1

#include <stdio.h>

int main() {
    register int a; // 变量a在CPU寄存器中分配内存,a的初始默认值为0
    printf("%d", a);
}

输出:

0

示例 2

#include <stdio.h>

int main() {
    register int a = 0;
    printf("%u", &a); // 这将导致编译时错误,因为无法获取寄存器变量a的地址
}

输出:

main.c:5:5: error: address of register variable 'a' requested
printf("%u", &a);
^~~~~~

外部(External)

  • 外部存储类用于告诉编译器在程序的其他地方声明具有外部链接的extern变量。
  • 声明为extern的变量不分配任何内存,它只是声明,用于指定变量在程序的其他地方声明。
  • 外部整型变量的默认初始值为0,否则为null。
  • 只能在全局范围内初始化extern变量,即无法在任何块或方法内初始化外部变量。
  • 外部变量可以声明多次,但只能初始化一次。
  • 如果将变量声明为外部变量,则编译器将在程序中搜索该变量的初始化位置,该位置可以是extern或static。如果没有找到,则编译器将显示错误。

示例 1

#include <stdio.h>

int main() {
    extern int a;
    printf("%d", a);
}

输出:

main.c:(.text+0x6): undefined reference to `a'
collect2: error: ld returned 1 exit status

示例 2

#include <stdio.h>

int a;

int main() {
    extern int a; // 变量a在全局范围内定义,不会分配内存给a
    printf("%d", a);
}

输出:

0

示例 3

#include <stdio.h>

int a;

int main() {
    extern int a = 0; // 这将显示编译时错误,因为无法同时使用extern和初始化器
    printf("%d", a);
}

输出:

编译时错误
main.c: In function 'main':
main.c:5:16: error: 'a' has both 'extern' and initializer
extern int a = 0;
^~~~~~

示例 4

#include <stdio.h>

extern int a;

int a = 20;

int main() {
    printf("%d", a);
}

输出:

20

示例 5

extern int a;
int a = 10;
#include <stdio.h>

int main() {
    printf("%d", a);
}

int a = 20; // 这将显示编译时错误

输出:

编译时错误

标签: c语言, c语言教程, c语言技术, c语言学习, c语言学习教程, c语言下载, c语言开发, c语言入门教程, c语言进阶教程, c语言高级教程, c语言面试题, c语言笔试题, c语言编程思想