C语言之变量的存储方式和生存周期

首先明确一下变量的划分方式。
根据变量的作用域,可以划分为:局部变量,全局变量
根据生存周期,可以划分为:静态存储方式,动态存储方式

  • 局部变量
    该变量只在一个局部范围内有效,比如在一个函数内定义的变量,或者在一个复合语句中定义的变量。
  • 全局变量(也称“外部变量”,下文所有提到的二者相等)
    程序的编译单位是远程许文件,一个源文件可以包涵一个或若干个函数。在函数外定义的变量即全局变量。
    注意:在同一个源文件中,全局变量与局部变量重名,在局部变量的范围内,局部变量有效,全局变量被“屏蔽”。(我把这叫做由小到大的原则)
    内存中用户使用的存储空间的情况是这样的:这里写图片描述
    数据分别存放在静态和动态存储区,全局变量全部存储在静态存储区,在程序开始执行时给全局变量分配存储区,程序执行完毕就释放,在执行过程中他们占据固定的存储单元。
    在动态存储区存放以下数据:
    1.函数形参,在调用函数时分配给形参存储空间;
    2.函数中定义的没有用static修饰的变量,及自动变量(后文会说)
    3.函数调用的现场保护和返回地址等。
    对于以上这些数据,在调用函数开始时分配动态存储空间,函数结束时释放这些空间。在函数执行过程中,这个分配和释放是动态的。比如一个程序中调用同一个函数两次,在这两次调用时,分配给局部变量的存储空间地址可能是不相同的。
    C语言中,每个函数和变量都有两个属性:数据类型数据的存储类别
    数据类型指的是整型,浮点型,等等。
    存储类别有:自动的(auto),静态的(static),寄存器的(register),外部的(extern).

局部变量的存储类别

  • 自动变量auto
    函数中的局部变量,如果不声明为static,都是动态分配存储空间的,数据存储在动态存储中。这类变量称为自动变量,自动变量用auto做存储类别声明。实际上我们编程时通常使用的都是auto存储,关键字auto可以不写,则隐含指定为“自动存储类别”。
  • 静态变量static
    有时候我们需要用到一个函数中的局部变量的值在此次函数调用之后不消失,而保持原值,即其,希望在下次调用该函数时,该变量已有值,就是上次函数函数调用结束之后的值。这时候我们就应该使用static关键字声明。
    这时候局部变量就变成了静态局部变量,在静态存储去内分配存储单元。注意:静态局部变量是在函数编译时赋初值的,在程序运行时它已经有初值。以后每次调用函数时就不再重新赋值,只是保留上一次函数调用结束时的值。虽然静态局部变量在函数调用结束后仍然存在,但是其他函数不能引用它,因为他是局部变量,只能被本函数引用,不能被其他函数引用。
  • 寄存器变量register
    一般情况下,变量(包括动态存储和静态存储方式)的值是存放在内存中的,当程序用到哪一个变量时,有控制器发出指令将内存中改变量的值送到运算器中。经过运算器运算,如果需要存数,再从运算器中奖数据送到内存存放。如果一些变量的存储读取在一个函数中要反复进行,可以声明为register存储类型,将变量的值存放在CPU中的寄存器中,由于寄存器的存取速度远远高于内存的存取速度,因此这样可以提高执行效率。

全局变量的存储类别

  • 在一个文件内扩展外部变量的作用域
    外部变量如果不在文件的开头定义,其有效范围就是其定义处到文件结束,所以定义点之前的函数是不能引用该变量的。为了解决这个问题,引入了extern关键字。在引用之前对变量作”外部变量声明“,表示把该变量的作用域扩展至此。例如:
#include <stdio.h>
int main(){
extern int a,b,c;
/*把外部变量的作用于扩展至此*/
sanf("%d %d %d",&a,&b,&c);
function(); 
}
int a,b,c;
/*定义外部变量abc,因为是在函数外部定义的所以是外部变量,但是其作用范围是从此处至之后的函数,main函数在其之前所以正常是不能引用的*/
int function(){
    printf("%d,%d,%d"a,b,c);
}

  • 将外部变量的作用扩展到其他文件
    同上述的上述,都是对外部变量的作用域的扩充,只是这次是跨文件范围的。如果两个文件都要用到一个变量Number,又不能在两个文件中分别定义一个Number外部变量。(会出现“重复定义”错误。)正确做法就是,在一个文件中定义外部变量Number,在另一个文件中用extern做“外部变量声明”,即extern Number;
    例如:
    在file1.c文件中:
#include <stdio.h>
int a;//声明外部变量a
int main(){
a=3;
}

在file2.c文件中:

extern a;//扩展作用域
void print(){
printf("%d",a);
}

可以发现,extern既可以把同一个文件中的外部变量作用域扩展,又可以扩展其他文件中的变量,系统怎么区别呢?在编译时如果遇到extern,现在本文件中寻找外部变量的定义,如果没有找到,就在连接时从其他文件中找,如果再找不到,就报错。(也是遵循由小到大的原则)

  • 将外部变量的作用限制在本文件中
    既然有扩展作用域的方法,自然有限制作用域的方法。对外部变量用关键字static声明,则就把该变量限制在本文件中,不可以被其他文件引用。
    注意:static关键字用于局部变量和外部变量其作用是不同的。局部变量原本存数在动态存储区,在用static声明之后,其存储空间就在静态存储区了;而全局变量,其存储空间一直在静态存储区,用static声明之后,只是限定了它作用域只能在本文件中。从作用域角度看,凡是static声明的,其作用域都是局限的,要么是局限于一个函数内(静态局部变量),要么是局限与本文件内(静态全局变量)。
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值