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 出 ...
随机推荐
- SAS学习笔记62 通过压缩变量长度来实现数据集压缩
有时候从其他数据库过来的字符型变量Length很长,导致数据集文件很大,可以通过压缩变量长度来实现数据集压缩 具体思路: LENGTH语句设置所有变量真实长度 SET数据集的时候对原有变量进行RENA ...
- quartz2.3.0(四)JobDataMap—带状态集合的定时器内置集合
任务类 package org.quartz.examples.example4; import java.util.Date; import org.quartz.DisallowConcurren ...
- [CF436D]Pudding Monsters
题目大意:有一个长度为$2\times 10^5$的板,有$n(n\leqslant 10^5)$个格子$a_1,\dots,a_n$有布丁怪兽,一开始连续的怪兽算一个怪兽,有$m(m\leqslan ...
- PHP写入文件
file_put_contents('log.txt',PHP_EOL.'zhangsan'.$time.'查看了数据', FILE_APPEND);
- Python之TensorFlow的模型训练保存与加载-3
一.TensorFlow的模型保存和加载,使我们在训练和使用时的一种常用方式.我们把训练好的模型通过二次加载训练,或者独立加载模型训练.这基本上都是比较常用的方式. 二.模型的保存与加载类型有2种 1 ...
- 在Unity中创建VR游戏
添加VR插件为了为您选择的平台创建VR游戏,我们需要下载几个插件.出于本教程的目的,我将向您展示如何上传到Android平台.要上传到iOS,您需要下载 Xcode. 现在让我们下载Unity的Goo ...
- node.js开发 1-概述
https://www.cnblogs.com/gaoya666/p/9071288.html Nodejs英文网:https://nodejs.org/en/ 中文网:http://nodejs.c ...
- Postgres 多实例实例部署方式
Postgres 数据库在原有示例正常运行情况下,新增一个端口示例,主要目的解决新的项目和原有项目的数据库部署不在冲突,可以独立运行,备份和还原数据互不影响,主要用的的命令有 initdb 数据库初 ...
- Android 低功耗蓝牙BLE 开发注意事项
基本概念和问题 1.蓝牙设计范式? 当手机通过扫描低功耗蓝牙设备并连接上后,手机与蓝牙设备构成了客户端-服务端架构.手机通过连接蓝牙设备,可以读取蓝牙设备上的信息.手机就是客户端,蓝牙设备是服务端. ...
- Android查看应用方法数
当一个项目快速迭代时,难免引进各种依赖,从而导致单个apk超过65k的限制.如何查询apk的方法数也是每个Android Developer必备技能. 我使用的是 dex-method-counts ...