/* * 12_变量的存储方式和生存期.c * * Created on: 2015年7月5日 * Author: zhong */ #include <stdio.h> #include <stdlib.h> /** * 从变量的作用域分: 全局变量,局部变量 * 从变量存在的时间(生命周期)分:静态存储方式。动态存储方式 * * 静态存储方式:在程序执行期间由系统分配固定的存储空间的方式 * 动态存储方式:在程序执行期间依据须要进行动态的分配存储空间的方式。 * * 数据存放的位置:静态存储区,动态存储区 * * 1:全局变量所有存放在静态存储区,当程序開始执行时给全局变量分配存储区。结束后释放。在执行期间占领固定存储单元,而不是动态地进行分配和释放。 * 2:动态存储区:形式參数,函数中定义的变量(不带statickeyword),函数调用时的现场保护和返回地址 * 动态存储区内分配存储单元,在程序整个执行期间都不会释放。 * * 在c语言中,每个变量和函数都有两个属性:数据类型(如:int,float)和数据的存储类别(静态,动态存储)。 * * c语言中存储类别包含4种:自己主动的(auto,默认) ,静态的(static),寄存器的(register),外部的的(extern) * 存储类别不同,变量的作用域和生存期也不同。 * *------------------------------------------- * 一:局部变量的存储类别: * 1:自己主动变量(默认的):在函数中的局部变量。假设不专门声名为static的。都是动态地分配存储空间的,数据存储在动态存储区中。* 调用函数会给这些变量分配存储空间。结束时自己主动释放存储空间 * 如:函数的形參。局部变量。 * 自己主动变量用keywordauto作存储类别的声明。 * * int f(int a){//形參 * auto int b,c=3; //int b,c=3; 自己主动局部变量。auto当然能够省略(我们平时就是省略的) * } * * 2:静态局部变量(static局部变量):仅仅是在局部变量int a;前面加个statickeyword static int a; 数据存储在静态存储区中。 * 特点:当函数结束后。静态局部变量的存储单元不会释放。当下次再调用这个函数时,这个值就是上一次调用时结束时产生的值。 * * 静态局部与自己主动局部变量比較: * 1:静态局部变量是在编译时赋初值,仅仅赋初值一次,在程序执行时它已经有初值。以后每次调用函数时不再又一次赋初值而仅仅是保留上次函数调用结束时的值 * 2:动态局部变量赋初值,不是在编译时进行的,而是在函数调用时进行的,每调用一次,函数又一次比例一次初值。 * 3:定义静态局部变量时不赋初值,系统会自己主动赋初值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 ",i,fac(i)); * } * * 3:寄存器变量(register): 将变量保存到cpu的寄存器中。 * 说明: * 一般变量(静态,动态存储方式)的值都 存放在内存中的,当程序用到上"控制器"发生指令将内存中这个变量的值送到"运算器"中进行运算, * 运算后。再从运算器将数据送到内存中存放。 * * 为什么要操作寄存器变量: * 比如在函数中执行1000次循环,每次循环中都 要引用局部变量(对某个变量频繁存取),假设每次都由“控制器”发送指令从内存中“存取”变量值,会花费不少时间。 * 将局部变量的值放在cpu的寄存器中,须要用的时间胻从寄存器取出參加运算,不必从内存中去存取。
速度超快的说。
* * 声明寄存器变量:register int f; * * 因为计算机的发展,优化的编译系统能够自己主动识别使用频繁的变量,从而自己主动将这些变量放在寄存器中。所以实际编程中,程序猿不须要过多指定这样的 变量。 * *------------------------------- *二:全局变量的存储类别: * * 全局变量都是存放在静态存储区中的,因此它们的生存期是固定的。
存在于程序执行的整个过程。 * 尽管生命周期是固定的,可是全局变量的作用域是不确定的,不同的存储类别作用域不同。 * * 普通情况下假设全局变量(外部变量)不在文件的开头定义(整个源文件)。其作用域在定义处開始,到本程序文件的未尾。
定义处之前的函数不能使用。
* * 假设不在文件开关定义,又想定义处之前的函数能使用这个全局变量,就要对全局变量进行作用域扩展 * 1:在一个文件内扩展外部变量的作用域 (extern) * 在函数引用这个在函数之后定义的外部变量时,使keywordextern对这个变量作“外部变量声明”:表示将外部变量的作用域扩展到此位置 * 如: * int fun(){ * extern int A; //extern对这个变量作“外部变量声明” * //...在这个函数后面语句就能够使用这个外部变量了 * } * int A=20; //在函数之后声名的外部变量 * * 2:将外部变量的作用域扩展到其他文件 * 将其他源文件里的全局变量扩展到本源文件加也是加个externkeyword就可以。 * * 如: * 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:将外部变量的作用域限制在本文件里(不让其他文件訪问):仅仅须要在定义外部变量时加入statickeyword就可以。 * 同一时候。加了statickeyword的全局变量的名称,其他文件也能够使用这个文件,不会发生冲突 * * 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 ", 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 ", 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 ",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; }