变量的储存
一、存储空间的情况
程序区 |
静态存储区 |
动态存储区 |
静态存储方式:在程序运行期间由系统分配固定的存储空间的方式。
动态存储方式:在程序运行期间根据需要进行动态的分配存储空间的方式。
二、数据存储位置
静态存储区:全局变量全部存放在静态存储区。
动态存储区:(1)函数形式参数。
(2)函数中定义的没有用关键字static声明的变量,即自动变量。
(3)函数调用时的现场保护和返回地址等。
三、变量与函数的属性
(1)数据类型;
(2)数据的存储类别;
c语言的存储类别:自动的(auto),静态的(static),寄存器的(register),外部的(extern)。
四、局部变量的存储类别
1. 自动变量(auto变量):不专门声明static(静态)存储类别,都动态的分布存储空间。若无关键字则暗指“自动存储类别”。
2. 静态局部变量(static局部变量):
例:
#include<stdio.h>
int main()
{
int f(int); //声明函数
int a=2,i; //自动局部变量a,i ,没有声明为static(静态)存储类别,自动分为自动变量
for(i=0;i<3;i++)
printf("%d\n",f(a)); //输出f(a)的值
return 0;
}
int f(int a) //定义f函数,a为形参
{
auto int b=0; //自动局部变量(auto),等价于int b=0
static c=3; //静态局部变量(static)
b=b+1;
c=c+1;
return(a+b+c);
}
静态局部变量:属于静态存储类别,在静态存储区内分配存储类别。在整个程序运行期间都不得释放。
自动变量:属于动态存储类别,分配在动态存储区空间,函数调用结束后即释放。
静态局部变量在编译时赋初值,且只赋初值一次。如果定义局部变量时不赋初值,编译时自动赋初值0(对数值型变量)或空字符'\0'(对自负变量)
自动变量的值是一个不确定的值。
静态局部变量在函数调用后仍然存在,但其他函数不可再调用。
例:输出1到5的阶乘值
#include<stdio.h>
int main()
{
int a(int n);
int i;
for(i=1;i<5;i++) //先后调用五次a函数
printf("%d!=%d\n",i,a(i)); //每次计算并输出i!(i阶乘)的值。
return 0;
}
int a(int n)
{
static int s=1; //s保留了上次调用结束时的值
s=s*n; //在上次的s值的基础上再乘以n
return(s); //返回值s是n!的值
}
静态存储要多占内存,降低程序的可读性。当调用次数过多时会导致不清楚当前值是什么,因此应少使用静态局部变量。
3.寄存器变量(register变量):经局部变量的值存放在CPU中的寄存器中,需要时直接取出参加运算,不再从内存中存取。
注:三种局部变量存储位置不同:自动变量存储在动态存储区;静态局部变量存储在静态存储区;寄存器存储在CPU中的寄存器中。
五、全局变量的存储类别
全局变量存放自静态存储区中,生存期固定,存在于程序的整个运行过程中。
1.在一个文件内扩展外部变量的作用域
例:
#include<stdio.h>
int main()
{
int max();
extern int A,B,C;//把外部变量A,B,C的作用域扩展到从此处开始,用extern对A,B,C进行“外部变量声明”
printf("请输入三个整数:");
scanf("%d %d %d",&A,&B,&C); //输入三个数给A,B,C
printf("最大数是%d\n",max());
return 0;
}
int A,B,C; //定义外部变量A,B,C
int max()
{
int n;
n=A>B?A:B; //把A和B中最的得数放在n中
if(C>n)
n=C; //将A,B,C中最大的数放在n中
return (n); 返回n的值
}
提倡将外部变量的定义放在引用他的所有函数之前,避免在函数中多加一个extern声明。
2.将外部变量的作用域扩展到其他文件
例:给定b的值,输入a和m,求a*b和a^m的值。
//文件1
#include<stdio.h>
int A; //定义外部变量
int main()
{
int power(int); //函数声明
int b=3,c,d,n;
printf("输入数字a和它的幂\n");
scanf("%d %d",&A,&n);
c=A*b;
printf("%d*%d=%d\n",A,b,c);
d=power(n);
printf("%d**%d=%d\n",A,n,d);
return 0;
}
//文件2
extern A; //把在文件1中已定义的外部变量的作用域扩展到本文件
int power(int m)
{
int i,y=1;
for(i=1;i<=m;i++)
y*=A;
return(y);
}
文件2的开头有一个extern声明,声明在本文件中出现的变量A是一个“在其他文件中定义过的外部变量”。本来外部变量A的作用域是文件1,但现在用extern声明将其作用于扩大到文件2。
应注意防止改变该全局变量的值,影响到另一个文件中全局变量的值,从而影响该文件中函数的执行结果。
3.将外部变量的作用域限制在本文件中
在定义外部变量是加一个static声明,是外部变量只限于本文件中引用,而不能被其他文件引用。
文件1
static int A;
int main()
{
....
}
文件2
extern A;
viod fun(int n)
{
...
A=A*n; //出错
...
}
文件1中定义的全局变量A,因使用了static声明,将A的作用域限制在本文件范围内。
文件2中使用了“extern A”但仍不能使用文件1中的全局变量A。
静态外部变量:加上“static”声明,只能用于本文件的外部变量。
声明局部变量的存储类型和声明全局变量的存储类型是不同的:
局部变量:声明存储类型的作用指定变量存储的区域(静态存储区或动态存储区)以及由此产生的生存期问题。
全局变量:声明存储类型的作用是变量作用域的扩展问题。
用static声明一个变量的作用:
对局部变量:把其分配在静态存储区,该变量在这整个程序执行期间不释放,其所分配的空间始终存在。
对全局变量:该变量的作用与直线与本文件模块中(即被声明的文件中)。
生存期
变量按其生存期可分为 动态变量和静态变量
变量只能在其生存期内被引用,而变量的作用域直接影响变量的生存期。
静态生存期:只要程序开始运行,其就被分配了内存,生存期与程序的运行期相同.
局部生存期:开始于程序执行经过其声明点时,结束于命名它的标识符所在的作用域尾.
动态生存期:可以随时创建,随时删除,创建和删除是程序员用内存操作函数进行的。