/*
* 12_变量的存储方式和生存期.c
*
* Created on: 2015年7月5日
* Author: zhong
*/
#include <stdio.h>
#include <stdlib.h>
/**
* 从变量的作用域分: 全局变量,局部变量
* 从变量存在的时间(生命周期)分:静态存储方式,动态存储方式
*
* 静态存储方式:在程序运行期间由系统分配固定的存储空间的方式
* 动态存储方式:在程序运行期间根据需要进行动态的分配存储空间的方式。
*
* 数据存放的位置:静态存储区,动态存储区
*
* 1:全局变量全部存放在静态存储区,当程序开始执行时给全局变量分配存储区,结束后释放,在执行期间占据固定存储单元,而不是动态地进行分配和释放。
* 2:动态存储区:形式参数,函数中定义的变量(不带static关键字),函数调用时的现场保护和返回地址
* 动态存储区内分配存储单元,在程序整个运行期间都不会释放。
*
* 在c语言中,每一个变量和函数都有两个属性:数据类型(如:int,float)和数据的存储类别(静态,动态存储)。
*
* c语言中存储类别包括4种:自动的(auto,默认) ,静态的(static),寄存器的(register),外部的的(extern)
* 存储类别不同,变量的作用域和生存期也不同。
*
*-------------------------------------------
* 一:局部变量的存储类别:
* 1:自动变量(默认的):在函数中的局部变量,如果不专门声名为static的,都是动态地分配存储空间的,数据存储在动态存储区中。
* 调用函数会给这些变量分配存储空间,结束时自动释放存储空间
* 如:函数的形参,局部变量。
* 自动变量用关键字auto作存储类别的声明。
*
* int f(int a){//形参
* auto int b,c=3; //int b,c=3; 自动局部变量,auto当然可以省略(我们平时就是省略的)
* }
*
* 2:静态局部变量(static局部变量):只是在局部变量int a;前面加个static关键字 static int a; 数据存储在静态存储区中。
* 特点:当函数结束后,静态局部变量的存储单元不会释放,当下次再调用这个函数时,这个值就是上一次调用时结束时产生的值。
*
* 静态局部与自动局部变量比较:
* 1:静态局部变量是在编译时赋初值,只赋初值一次,在程序运行时它已经有初值,以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值
* 2:动态局部变量赋初值,不是在编译时进行的,而是在函数调用时进行的,每调用一次,函数重新比例一次初值。
* 3:定义静态局部变量时不赋初值,系统会自动赋初值0,或空字符‘\0’。对于自动变量来说,如果定义时不赋初值,系统会随机分配一个不确定的存储单元,所以值不确定。
* 4:静态局部变量在函数调用结束后仍然存在,但是其它函数不能引用。
*
* 静态局部变量使用场景:需要保留函数上一次调用结束时的值
* 如:输出1到5的阶乘值
* int fac(int n){
* static int fac=1;
* fac=fac*n;
* return fac;
* }
*
* int main(){
* int i;
* for(i=1;i<=5;i++)
* printf("%d!=%d\n",i,fac(i));
* }
*
* 3:寄存器变量(register): 将变量保存到cpu的寄存器中。
* 说明:
* 一般变量(静态,动态存储方式)的值都 存放在内存中的,当程序用到上"控制器"发生指令将内存中这个变量的值送到"运算器"中进行运算,
* 运算后,再从运算器将数据送到内存中存放。
*
* 为什么要操作寄存器变量:
* 例如在函数中执行1000次循环,每次循环中都 要引用局部变量(对某个变量频繁存取),如果每次都由“控制器”发送指令从内存中“存取”变量值,会花费不少时间。
* 将局部变量的值放在cpu的寄存器中,需要用的时间胻从寄存器取出参加运算,不必从内存中去存取。速度超快的说。
*
* 声明寄存器变量:register int f;
*
* 由于计算机的发展,优化的编译系统能够自动识别使用频繁的变量,从而自动将这些变量放在寄存器中。所以实际编程中,程序员不需要过多指定这种 变量。
*
*-------------------------------
*二:全局变量的存储类别:
*
* 全局变量都是存放在静态存储区中的,因此它们的生存期是固定的。存在于程序运行的整个过程。
* 虽然生命周期是固定的,但是全局变量的作用域是不确定的,不同的存储类别作用域不同。
*
* 一般情况下如果全局变量(外部变量)不在文件的开头定义(整个源文件),其作用域在定义处开始,到本程序文件的未尾。定义处之前的函数不能使用。
*
* 如果不在文件开关定义,又想定义处之前的函数能使用这个全局变量,就要对全局变量进行作用域扩展
* 1:在一个文件内扩展外部变量的作用域 (extern)
* 在函数引用这个在函数之后定义的外部变量时,使关键字extern对这个变量作“外部变量声明”:表示将外部变量的作用域扩展到此位置
* 如:
* int fun(){
* extern int A; //extern对这个变量作“外部变量声明”
* //...在这个函数后面语句就可以使用这个外部变量了
* }
* int A=20; //在函数之后声名的外部变量
*
* 2:将外部变量的作用域扩展到其它文件
* 将其它源文件中的全局变量扩展到本源文件加也是加个extern关键字即可。
*
* 如:
* file 1.c:
* int A=20;
* int max(){
* A=3;
* }
*
* file2.c:
* int funk(){
* extern int A; //将file 1.c 中定义的全局变量a扩展到这个文件,当作这文件的局部变量,int可省略
* A=34;
* }
* extern A;//将file 1.c 中定义的全局变量a扩展到这个文件,当作这文件的外部变量,在此之后的函数可用,之前的函数不可用
* int funk(){
* A=3; //在此之后的函数可用
* }
*
* (静态外部变量)
* 3:将外部变量的作用域限制在本文件中(不让其它文件访问):只需要在定义外部变量时添加static关键字即可。
* 同时,加了static关键字的全局变量的名称,其它文件也可以使用这个文件,不会发生冲突
*
* static int A=20; //这样其它文件就不能访问这个外部变量了。
* int main(){
*
* }
*
*
*小结:
* 一: static声明一个变量的作用:
* 1:对局部变量用static声明,把它分配在静态存储区,这变量在整个程序执行期间不释放
* 2:对全局变量用static声明,则这变量的作用域只限于 本文件模块,其它文件不可引用
*
*二: 声明存储类型的作用
* 对于局部变量来说,声明存储类型的作用是指定变量存储的区域(静态存储,动态存储,寄存器),以及由此产生的生存期的问题
* 对于全局变量,由于在编译时分配内存的,都 存放在静态存储区中,声明存储类型的作用是变量作用域的扩展问题,无它。
*
*
*/
//局部静态,动态变量
void local_static_auto(int a) {
auto int b = 1; //auto可以省略 自动变量
static int c = 3; //定义静态变量,程序运行期间,其存储单元不会释放,这语句只会在编译时执行一次,运行后不再执行。
//当第二次调用时,不会再重新赋初值3,只会使用前一次调用后保存的值
printf("第%d次运行:b=%d,c=%d,a+b+c=%d\n", a, b, c, (a + b + c));
c++; //c自增后保存在存储单元中,不释放,以便函数下次被调用时使用 .
b++; //自动变量在这里自增后也没用,因为
}
void test_local_static_auto() {
int i;
for (i = 1; i < 5; i++) {
local_static_auto(i);
}
/**
* output:
第1次运行:b=1,c=3,a+b+c=5
第2次运行:b=1,c=4,a+b+c=7
第3次运行:b=1,c=5,a+b+c=9
第4次运行:b=1,c=6,a+b+c=11
*/
}
//求n的阶乘
int fac(int n) {
static int fac = 1; //记录乘积结果
fac *= n;
return fac;
}
void test_fac() {
int i;
for (i = 1; i <= 5; i++)
printf("%d!=%d\n", i, fac(i));
/*1!=1
2!=2
3!=6
4!=24
5!=120*/
}
extern a;//将11_全局变量.c中定义的全局变量a扩展到这个文件,在此之后的函数可用,之前的函数不可用
//使用此函数之后 定义的外部变量
void use_extern_variable(){
extern int A; //把外部变量a的作用域扩展到从此处开始
// extern A; //类型名可写可不写
A=30;
printf("extern_variable A=%d ,other file a=%d\n",A,a);
}
int A=20;
int main12() {
// test_local_static_auto();
// test_fac();
use_extern_variable();
extern a; //将11_全局变量.c中定义的全局变量a扩展到这个方法里面,其它方法不能用
printf("%d",a);
return 0;
}
C语言学习笔记:12_变量的存储方式和生存期
最新推荐文章于 2023-01-08 00:50:50 发布