在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种类型的更多相关文章

  1. C语言中变量的存储类型

    在C语言中,对变量的存储类型说明有以下四种: auto 自动变量register   寄存器变量extern 外部变量static   静态变量 自动变量和寄存器变量属于动态存储方式,外部变量和静态变 ...

  2. C语言中变量的存储方式

    变量可以分为全局变量.静态全局变量.局部变量和静态局部变量变量的声明有两种情况:1)一种是需要建立存储空间的(定义性声明).例如int a 在生命的时候就已经建立了存储空间.2)另一种是不需要建立存储 ...

  3. C/C++——C++变量的作用域与生命周期,C语言中变量的作用域和生命周期

    全局变量 作用域:全局作用域(全局变量只需在一个源文件中定义,就可以作用于所有的源文件.) 生命周期:程序运行期一直存在 引用方法:其他文件中要使用必须用extern 关键字声明要引用的全局变量. 内 ...

  4. C语言中变量和函数的作用域和链接属性

    C语言中变量和函数的作用域和链接属性 作用域 代码块作用域: 代码块指的是使用"{}"包围起来的部分. 在代码块中定义的变量,代码块之外是不能访问的. 代码块嵌套之后的变量作用域, ...

  5. C语言中变量、全局变量与变量的作用域

    什么是变量: 变量常量都是表征数据的一种形式:常量用来表示数据的值: 变量不仅可以用来表示数据的值:还可以用来存放数据:因为变量对应着一定的内存单元: 变量和常量必须先定义后使用. 变量名和常量名都是 ...

  6. C语言中变量的作用域和生命周期

    变量的类型: 1. 局部变量和全局变量 局部变量也称为内部变量. 局部变量是在函数内作定义说明的.其作用域仅限于函数内, 离开该函数后再 使用这种变量是非法的. 全局变量也称为外部变量,它是在函数外部 ...

  7. c语言中变量和函数作用域深究

    首先,函数的作用域和访问权限基本可以参考 C语言中的作用域,链接属性和存储类型 也存在例外情况,比如内联函数 static inline,使用static 修饰 inline之后外部文件也可以访问内联 ...

  8. C语言中变量名及函数名的命名规则与驼峰命名法

    一.C语言变量名的命名规则:(可以字母,数字,下划线混合使用) 1. 只能以字母或下划线开始:2. 不能以数字开始:3. 一般小写:4. 关键字不允许用(eg:int float=2//error  ...

  9. 【转载】java 中变量的存储位置

    原文链接点这里,感谢博主分享 * 寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. * 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出 ...

随机推荐

  1. 少儿编程|Scratch编程教程系列合集,总有一款适合你

    如果觉得资源不错,友情转发,贵在分享!!! 少儿编程Scratch: 少儿编程Scratch第一讲:Scratch完美的初体验少儿编程Scratch第二讲:奇妙的接球小游戏少儿编程Scratch第三讲 ...

  2. linux 系统扩容 VMware Centos---VMware ESXi

    用到的命令 df  fdisk  pvcreate   pvdisplay    vgdisplay    vgextend    lvdisplay    lvextend  resize2fs 0 ...

  3. GZOI/GXOI2019

    陆陆续续做完了-- 与或和(单调栈) 这是一道一眼题-- 看到位运算,按位考虑贡献.对于每一位,将矩阵中的元素变为"当前元素的这一位是否为\(1\)",那么原矩阵变为\(01\)矩 ...

  4. new Image 读取宽高为0——onload

    获取图片一张图片的大小 let img = new Image() img.src = imgUrl if ( img.width != 375 || img.height != 200 ) { me ...

  5. oracle数据库 部分函数的用法

    select * from tab; //获取当前用户的数据库的所有表名 select sys_guid(),UserName from TESTLIKUI; //获取guid select sys_ ...

  6. springDataRedis的小demo

    1. 导入相关的依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...

  7. 全面学习 Python 包:包的构建与分发

    首发于公众号:Python编程时光 1. 为什么需要对项目分发打包? 平常我们习惯了使用 pip 来安装一些第三方模块,这个安装过程之所以简单,是因为模块开发者为我们默默地为我们做了所有繁杂的工作,而 ...

  8. SWD下载k60

    转:JTAG各类接口针脚定义,含义及SWD接线方式 IAR设置如下

  9. vue-cli 3.0 安装

    一.安装vue-cli 脚手架命令 npm install -g vue-cli   适用于vue-cli 2.0 npm install -g @vue/cli 适用于vue-cli 3.0 卸载命 ...

  10. [转]关于ORA-00979 不是 GROUP BY 表达式错误的解释

    转自:https://www.cnblogs.com/vigarbuaa/archive/2012/06/25/2561225.html ORA-00979 不是 GROUP BY 表达式”这个错误, ...