C语言教程-详解C语言中的存储类

C中的存储类用于确定变量的生存期、可见性、内存位置和初始值。C语言有四种存储类:
- 自动(Automatic)
- 外部(External)
- 静态(Static)
- 寄存器(Register)
存储类 | 存储位置 | 默认值 | 作用域 | 生命周期 |
---|---|---|---|---|
auto | RAM | 未初始化值 | 局部 | 函数内部 |
extern | RAM | 0 | 全局 | 整个主程序的结束前,可以在程序中的任何地方声明 |
static | RAM | 0 | 局部 | 整个主程序的结束前,保留在多次函数调用之间的值 |
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; // 这将显示编译时错误
输出:
编译时错误