C语言中【变量】的存储类型共有4种类型
在C语言中,对变量的存储类型说明有以下四种:
auto 自动变量 (动态存储)
register 寄存器变量(动态存储)
extern 外部变量(静态存储)
static 静态变量(静态存储)
所谓存储类型是指变量占用内存空间的方式,也称为存储方式。
这4种类型 不允许重复定义 如: extern static int a=200;是错误的;只能指定一中存储类型;如;static int a =200;或者是 extern int a;
变量的存储方式可分为“静态存储”和“动态存储”两种。
静态存储变量:在定义时候存储单元里一直保持不变;直到程序结束。
动态存储变量:在程序执行时候;使用他的时候才分配内存单元,使用完毕后立即释放,再使用在分配。
从以上分析可知,静态存储变量是一直存在的,而动态存储变量则时而存在时而消失。
一个变量属于哪一种存储方式,并不能仅从其变量作用域(文件,函数体,代码块,函数声明)来判断,还应有明确的存储类型说明;
如:static int a=20;
变量说明的完整形式应为:【存储类型说明符】【 数据类型说明符】【 变量名,变量名....】;
一、从作用域看:
1)全局变量
具有全局作用域。全局变量只需在一个源文件中定义,就可以作用于所有的源文件。
当然,其他不包含全局变量的定义的源文件需要用extern关键字再次声明这个全局变量。
2)静态局部变量(只对自己函数体内有效可见)
静态局部变量具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行结束一直存在,
它和全局变量的区别在于全局变量对所有函数都是可见的,
而静态局部变量只对定义自己的函数体始终可见。
局部变量也只有局部作用域,它是自动对象(auto),它在程序运行期间不是一直存在,
而是只在函数执行期间存在,函数的一次调用执行结束后,变量被撤销,
其所占用的内存也被收回。
静态全局变量也具有全局作用域,它与全局变量的区别在于如果程序包含多个文件的话,
它作用于定义它文件里,不能作用到其他文件里,
即被static关键字修饰过的变量具有文件作用域。
这样即使两个不同的源文件都定义了相同名字的静态全局变量,它们也是不同的变量。
二、从分配空间看:
全局变量,静态局部变量,静态全局变量都在静态存储区分配空间,而局部变量在栈里分配空间。
全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。
这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,
当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一个源程序的其他源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其他源文件中引起错误。
(1)静态变量会放在程序的静态数据存储区(全局可见)中,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与堆栈变量和堆变量的区别。
(2)变量用static告知编译器,自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。
从以上分析可以看出,把全局变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。因此static这个说明符在不同的地方所起的作用是不同的。应予以注意:
Tips:
A.若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块之间的耦合度。
B.若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块之间的耦合度。
C.设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题,因为他们都放在静态数据存储区,全局可见;
D.如果我们需要一个可重入的函数,那么我们一定要避免函数中使用static变量(这样的函数被称为:带“内部存储器”功能的函数)。
E.函数中必须要使用static变量情况:比如当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针。
附加说明:
变量的存储类型
auto int a = 10;自动变量 系统默认都是自动变量默认不会初始化;会产生随机数
static int a=20; 默认会被初始化;并仅仅初始化一次;生命周期整个程序
extern int a; 外部变量(全局变量) 默认会被初始化;并仅仅初始化一次 生命周期整个程序
register int a; 存放在cpu寄存器当中;不能用static 修饰;并且只能是局部变量、要求性能高的时候用
如:
register int y = 10; //错误
int get(){
register int x = 10; //正确
}
函数的局部变量
{
作用域只在函数体内;//压到栈 ,使用完后会被弹出释放;
}
文件main.c
#include <stdio.h>
/*
auto 自动变量
register 寄存器变量
extern 外部变量
static 静态变量
*/
int a = 100; //全局变量 其他文件可以用extern调用
//register int x = 10; //错误
extern void get();
static int name2 = 490; //全局静态变量 其他文件无法使用
int main()
{
get(); //分配1次 栈的空间有可能不是同一个
get(); //分配1次 栈的空间有可能不是同一个
get(); //分配1次 栈的空间有可能不是同一个
return 0;
}
文件1:
#include <stdio.h>
int abc = 2; //默认auto类型 //
static int name = 8890;
//extern static int name2; //错误;不允许定义2个存储类型
void get(){
extern int a;//引用全局变量
int aa = a;
a++;
auto int b = 20;
b++;
static int c = 20;//静态局部变量
c++;
register int r =30;
r++;
name++;
abc++;
printf("a=%d b=%d c=%d r=%d name=%d abc=%d\n",aa,b,c,r,name,abc);
}
//局部变量在栈上
/* 用户空间
(栈【局部变量】、堆、数据段【全局变量(静态全局,静态局部,动态变量)】、代码段)
*/
//全局变量在数据段存储
/* 数据段包括两部分(静态存储区、动态存储区)
静态存储区
【
全局变量(非静态,静态的全局;静态局部变量)
静态变量(全局和局部2种静态)
data初始化区
bss未出化区
全部变量: auto int a; static int a; 函数内部的局部静态变量static int b;
静态变量就分全局和局部2种;
】
*/
C语言中【变量】的存储类型共有4种类型的更多相关文章
- C语言中变量的存储类型
在C语言中,对变量的存储类型说明有以下四种: auto 自动变量register 寄存器变量extern 外部变量static 静态变量 自动变量和寄存器变量属于动态存储方式,外部变量和静态变 ...
- C语言中变量的存储方式
变量可以分为全局变量.静态全局变量.局部变量和静态局部变量变量的声明有两种情况:1)一种是需要建立存储空间的(定义性声明).例如int a 在生命的时候就已经建立了存储空间.2)另一种是不需要建立存储 ...
- C/C++——C++变量的作用域与生命周期,C语言中变量的作用域和生命周期
全局变量 作用域:全局作用域(全局变量只需在一个源文件中定义,就可以作用于所有的源文件.) 生命周期:程序运行期一直存在 引用方法:其他文件中要使用必须用extern 关键字声明要引用的全局变量. 内 ...
- C语言中变量和函数的作用域和链接属性
C语言中变量和函数的作用域和链接属性 作用域 代码块作用域: 代码块指的是使用"{}"包围起来的部分. 在代码块中定义的变量,代码块之外是不能访问的. 代码块嵌套之后的变量作用域, ...
- C语言中变量、全局变量与变量的作用域
什么是变量: 变量常量都是表征数据的一种形式:常量用来表示数据的值: 变量不仅可以用来表示数据的值:还可以用来存放数据:因为变量对应着一定的内存单元: 变量和常量必须先定义后使用. 变量名和常量名都是 ...
- C语言中变量的作用域和生命周期
变量的类型: 1. 局部变量和全局变量 局部变量也称为内部变量. 局部变量是在函数内作定义说明的.其作用域仅限于函数内, 离开该函数后再 使用这种变量是非法的. 全局变量也称为外部变量,它是在函数外部 ...
- c语言中变量和函数作用域深究
首先,函数的作用域和访问权限基本可以参考 C语言中的作用域,链接属性和存储类型 也存在例外情况,比如内联函数 static inline,使用static 修饰 inline之后外部文件也可以访问内联 ...
- C语言中变量名及函数名的命名规则与驼峰命名法
一.C语言变量名的命名规则:(可以字母,数字,下划线混合使用) 1. 只能以字母或下划线开始:2. 不能以数字开始:3. 一般小写:4. 关键字不允许用(eg:int float=2//error ...
- 【转载】java 中变量的存储位置
原文链接点这里,感谢博主分享 * 寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. * 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出 ...
随机推荐
- [高清·非影印] 深度学习入门:基于Python的理论与实现 + 源代码
------ 郑重声明 --------- 资源来自网络,纯粹共享交流, 如果喜欢,请您务必支持正版!! --------------------------------------------- 下 ...
- js调用浏览器复制
<script type="text/javascript"> function copyUrl2() { var Url2=document.getElementBy ...
- springboot笔记07——整合MyBatis
前言 Springboot 整合 MyBatis 有两种方式,分别是:"全注解版" 和 "注解.xml混合版". 创建项目 创建Springboot项目,选择依 ...
- 关于 JS this
关于 JS this 1. this 与 普通函数 2. this 与 bind.call.apply 3. this 与 箭头函数 4. this 与 return 4.1 返回 引用对象 4.2 ...
- Fatal error: Uncaught Error: Call to a member function bind_param() on boolean
1.2019年10月22日 PHP写mysqli 预编译查询的时候报错. Fatal error: Uncaught Error: Call to a member function bind_par ...
- UCOSIII等待多个内核对象
内核对象 内核对象包括信号量.互斥信号量.消息队列和事件标志组 UCOSIII中允许任务同时等待多个信号量和多个消息队列 主结构体 typedef struct os_pend_data OS_PEN ...
- iPhone的xib与iPad的xib相互转换
1. xib转换 iPhone版本APP开发完成后需要再开发iPad版本的APP,需要把iPhone版本的xib文件添加到iPad项目中去,但是Xcode中iPhone和iPad使用的xib格式不能完 ...
- Ldr和bl指令
Ldr和bl在启动程序中,都是可以负责pc跳转的指令. 1)bl是地址无关指令,和什么地址无关呢?和当前的运行地址无关,链接器脚本中标明了一个运行地址,但是arm中的代码实际是从地址0开始运行的.这个 ...
- c# 表达式目录树拷贝对象(根据对象类型动态生成表达式目录树)
表达式目录树,在C#中用Expression标识,这里就不介绍表达式目录树是什么了,有兴趣可以自行百度搜索,网上资料还是很多的. 这里主要分享的是如何动态构建表达式目录树. 构建表达式目录树的代码挺简 ...
- python(列表函数)
一.列表函数 1.sort()原址排序 参数默认reverse=False时为正序排序 list1 = [1,3,5,2,1,23,18] list1.sort() print (list1) 当参数 ...