一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第22天,点击查看活动详情。
局部变量的存储类别
- 1. 自动变量(auto变量) 函数种的局部变量,不是专门声明为static(静态)存储类别,都是动态地分配存储空间的,数据存储在动态存储区种。例如函数中的形参和函数/复合语句中定义的局部变量都属于此类。在调用该函数时,系统会给这些变量分配存储空间,在函数调用结束时就自动释放这些存储空间。因此这类局部变量称为自动变量。自动变量用关键字auto作存储类别的声明
int f(int a) // 定义f函数,a为形参
{
auto int b, c = 3; // 定义自动变量b,c
.
.
.
}
关键字auto可以省略,不写auto则隐含指定为“自动存储类别”,它属于动态存储方式
- 2. 静态局部变量(static局部变量) 静态局部变量是指 函数中的局部变量的值在函数调用结束后不消失而继续保留原值,及其占用的存储单元不释放,在下一次再调用该函数时,该变量已有值(就是上一次函数调用结束时的值),用关键字static进行声明
#include <stdio.h>
int main(){
// ⑨ 静态局部变量
int f(int); // 函数声明
int a = 2, i; // 自动局部变量
for(i = 0; i < 3; i++) {
printf("%d\n", f(a)); // 输出f(a)的值
}
return 0;
}
int f(int a) {
auto int b = 0; // 自动局部变量
static int c = 3; // 静态局部变量
b +=1;
c+=1;
return a + b + c;
}
- 静态局部变量属于静态存储类别,在静态存储区内分配存储单元。在程序整个运行期间都不释放。而自动变量(即动态局部变量)属于动态存储类别,分配在动态存储区空间而不在静态存储区空间,函数调用结束后即释放。
- 对静态局部变量是在编译时赋初值的,即只赋初值一次,在程序运行时它已有初值。 自动变量赋初值,不是在编译时进行的,而是在函数调用时进行的,每调用一次函数重新给一次初值,相当于执行一次赋值语句
- 如果定义局部变量不赋初值的话: 静态变量——编译时自动赋初值0或空字符'\0'; 自动变量——它的值是一个不确定的值
- 虽然静态局部变量在函数调用结束后让人存在,但其他函数是不能引用它的。因为它是局部不安了,只能被本函数引用,而不能被其他函数引用。
#include <stdio.h>
int main() {
// 10 输出1到5的阶乘值 --- 静态局部变量
int fac1(int n); // 函数声明
int i;
for (i = 1; i <= 5; i++) { // 先后5次调用fac1函数
printf("%d!=%d\n", i, fac1(i)); // 每次计算并输出i!的值
}
return 0;
}
int fac1(int n) {
static int f = 1; // f保留了上次调用结束时的值
f = f * n; // 在上次的f值基础上在乘以n
return f; // 返回值f是n!的值
}
- 3.寄存器变量(register变量) 一般情况下,变量(包括静态存储方式和动态存储方式)的值是存放在内存中的。当程序中用哪一个变量的值时,由控制器发出指令将内存中该变量的值送到运算器中。经过运算器进行运算,如果需要存数,再从运算器将数据送到内存存放,见下图
寄存器变量(register关键字):如果有一些变量使用频繁,则为存取变量的值要花费不少时间。为提高执行效率,允许将局部变量的值放在CPU中的寄存器中,需要用时直接从寄存器取出参加运算,不必再到内存中去取。由于对寄存器的存取速度远高于对内存的存取速度,因此这样做可以提高执行效率。
register int f; // 定义f为寄存器变量
3种局部变量的存储位置是不同的:
- 自动变量:存储在动态存储区
- 静态局部变量:存储在静态存储区
- 寄存器:存储在CPU中的寄存器中
全局变量的存储类别
全局变量是存放在静态存储区中的。因此它们的生存期是固定的,存在于程序的整个运行过程。
一般来说,外部变量是在函数的外部定义的全局变量,它的作用域是从变量的定义处开始,到本程序文件的末尾。在此作用域内,全局变量可以为程序中各个函数所引用。但是有时程序设计任意希望能扩展外部变量的作用域。有以下几种情况:
- 在一个文件内扩展外部变量的作用域
- 将外部变量的作用域扩展到其他文件
- 将外部变量的作用域限制在本文件中
※ 用static声明一个变量的作用是:
- 对局部变量用static声明,把它分配在静态存储区,该变量在整个程序执行期间不释放,其所分配的空间始终存在
- 对全局变量用static声明,则该变量的作用域只限于本文件模块(即被声明的文件中)
存储类别小结
对一个数据的定义,需要指定两种属性:数据类型和存储类别, 分别使用两个关键字
static int a; // 静态局部整型变量或静态外部整型变量
auto char c; // 自动变量,在函数内定义
register int d; // 寄存器变量,在函数内定义
extern b; // 将已定义的外部变量b的作用域扩展到此
- 从作用域角度分,有局部变量和全局变量。
- 局部变量
- 自动变量:即动态局部变量(离开函数,值就消失)
- 静态局部变量(离开函数,值仍保留)
- 寄存器变量(离开函数,值就消失)
- (形式参数可以定义为自动变量或寄存器变量)
- 全局变量
- 静态外部变量(只限本文件引用)
- 外部变量(即非静态的外部变量,允许其他文件引用)
- 从变量存在的时间(生存期) 来区分,有动态存储和静态存储两种类型。静态存储是程序整个运行时间都存在,而动态存储则是在调用函数时临时分配单元
- 静态存储
- 静态局部变量(函数内有效)
- 静态外部变量(本文件内有效)
- 外部变量(用extern声明后,其他文件可引用)
- 动态存储
- 自动变量(本函数内有效)
- 寄存器变量(本函数内有效)
- 形式参数(本函数内有效)
- 从变量值存放的位置来区分
- 内存中静态存储区
- 静态局部变量
- 静态外部变量(函数外部静态变量)
- 外部变量(可为其他文件引用)
- 内存中动态存储区:自动变量和形式参数
- CPU寄存器:寄存器变量
- 为什么要用函数
- 怎样定义函数
- 调用函数
- 对被调用函数的声明和函数原型
- 函数的嵌套调用
- 函数的递归调用
- 数组作为函数参数
- 局部变量和全局变量
- 变量的存储方式和生存期
- 关于变量的声明和定义
- 内部函数和外部函数