c程序中所有的全局变量都是静态存储的_零基础学C语⾔
(7):存储类型
前四节,我们从编写⼀个计算器的⾓度,讨论出编程语⾔需要数据类型、变量和常量,并详细介绍了这三个概念。那么编写⼀个计算器还需要哪些东西呢?
我们想想看,当我们想设计⼀个⽐较复杂的程序,例如开发⼀款游戏时,我们不可能写在⼀个⽂件下吧,那这个⽂件得多庞⼤。
⽐如说王者荣耀,是⼀个团队共同开发的,例如我设计韩信的动作和技能介绍,他设计李⽩的凤求凰⽪肤,另⼀个⼈设计镜的出装。⽤膝盖想⼀想,这么多⼈不可能围在⼀起对⼀个⽂件指指点点,否则策划与程序员之间,岂不是天天“你在教我做事?”
虽然不在⼀块,但各个⽂件之间没有交流么?
有时候李⽩和王昭君在同⼀局游戏碰到,会产⽣⼀些奇怪的台词,所以不同⽂教是有交流的,那怎么产⽣联系呢?
这就是今天的重点——存储类型。
存储类型是⼲嘛的呢?
简单来说,存储类型是⽤来定义C程序变量/函数的范围(可见性)和⽣命周期的。具体分为四类:auto、register、static、extern。
我们挨个来看:
auto存储类
auto是⽤来修饰局部变量的,如果局部变量前没有存储类型,默认为auto类型,例如我们通常看到的int a;,实际是auto int a;。register存储类
register是寄存器类型,顾名思义,是把修饰的变量放到寄存器中,⽬的是为了提⾼程序的运⾏效率。但要记住,不管是单⽚机也好,计算机也罢,任何CPU的寄存器资源都是有限的,如果寄存器满了,被修饰的变量就会默认回到auto类型。
⼀般格式:register 数据类型 变量;
extern存储类
前⾯提过,如何在不同⽂件之间交流?
嘿嘿,extern就是⼀个很好的⽅法。
c语言如何去学extern是外部引⽤类型,主要是引⽤统⼀⼯程中的全局变量或函数,什么意思呢?就是说,我想⽤其他⽂件的变量或函数,那么就需要使⽤extern这个关键字。
我们上⼀节提到过,定义在内存上是分配空间的,⽽使⽤extern是在声明,意思是告诉编译器该变量存在空间,但并不是在声明处开辟的空间。
怎么去⽤呢?
假设在第⼀个c⽂件,我们定义:int a;在另⼀个⽂件我们想要使⽤第⼀个⽂件中的a,我们就需要在第⼆个c⽂件中加上extern int a;这样这个a就在这两个⽂件共享。
static存储类
static这个关键字⾮常重要,为啥呢?因为⾯试题经常考。
当static修饰全局变量或函数时,限制变量或函数的作⽤域,表⽰只能在本⽂中使⽤;当static修饰局部变量时,改变局部变量的存放位置,延长局部变量的⽣命周期,运算的结果保留上⼀次的结果。
“改变局部变量的存放位置”,怎么理解这句话呢?
这就要提到C语⾔的内存管理了,这个我们后⾯详细说,这⾥我们简单提⼀下:
⾸先,我们要知道计算机中的内存是分区来管理的,程序和程序之间的内存是独⽴的,不能互相访问,⽐如QQ和王者荣耀分别所占的内存区域是不能相互访问的。⽽每个程序的内存也是分区管理的,⼀个应⽤程序所占的内存可以分为很多个区域。
我们需要了解的区域有四个,分别是栈区、堆区、静态区和代码区。通常我们定义的局部变量,是存放在栈区的,并且局部变量的⽣命周期在该语句块执⾏结束时便结束了。
但我们⽤static修饰,该变量便存放在静态数据区,其⽣命周期⼀直持续到整个程序执⾏结束。但是其作⽤域并没有改变,它仍然是⼀个局部变量,作⽤域仅限于该语句块。
⽽当static修饰全局变量或函数时,该变量或函数仅在本⽂使⽤,就没法和其他⽂件产⽣交流,⽤extern关键字都不⾏。
这个我们⼀般什么时候⽤呢?
因为每⼀个⼤⼯程都不是⼀个⼈完成的,当某⼈在某⼀⽂件使⽤⼀个全局变量时,另⼀个⼈在其他⽂件可能也定义了⼀个相同的全局变量,这样会发⽣冲突,所以⼲脆⽤static修饰,以防发⽣奇怪的BUG。
因为有了static这个关键字,变量从全局变量和局部变量这两种,就变成了全局变量、局部变量、静态全局变量、静态局部变量四种。
他们之间怎么区别呢?
全局变量、局部变量、静态全局变量、静态局部变量的区别
从作⽤域看:
1、全局变量具有全局作⽤域。全局变量只需在⼀个源⽂件中定义,就可以作⽤于所有的源⽂件。当然,其他不包含全局变量定义的源⽂件需要⽤extern 关键字再次声明这个全局变量。
2、静态局部变量具有局部作⽤域,它只被初始化⼀次,⾃从第⼀次被初始化直到程序运⾏结束都⼀直存在,它和全局变量的区别在于全局变量对所有的函数都是可见的,⽽静态局部变量只对定义⾃⼰的函数体始终可见。
3、局部变量也只有局部作⽤域,它是⾃动对象(auto),函数的⼀次调⽤执⾏结束后,变量被撤销,其所占⽤的内存也被收回。
4、静态全局变量也具有全局作⽤域,它作⽤于定义它的⽂件⾥,不能作⽤到其它⽂件⾥,即被static关键字修饰过的变量具有⽂件作⽤域。这样即使两个不同的源⽂件都定义了相同名字的静态全局变量,它们也是不同的变量。
从分配内存空间看:
1、全局变量,静态局部变量,静态全局变量都在静态存储区分配空间,⽽局部变量在栈⾥分配空间。
2、全局变量本⾝就是静态存储⽅式, 静态全局变量当然也是静态存储⽅式。这两者的区别虽在于⾮静态全局变量的作⽤域是整个源程序。⽽静态全局变量则限制了其作⽤域,即只在定义该变量的源⽂件内有效,在同⼀源程序的其它源⽂件中不能使⽤它。
· 1)静态变量会被放在程序的静态数据存储区(全局可见)中,这样可以在下⼀次调⽤的时候还可以保持原来的赋值。这⼀点是它与堆栈变量和堆栈变量和堆变量的区别。
· 2)变量⽤static告知编译器,⾃⼰仅仅在变量的作⽤范围内可见。这⼀点是它与全局变量的区别。
总结
本节介绍了auto、register、static、extern这四种存储类型,并介绍了全局变量、局部变量、静态全局变量、静态局部变量这四种变量的区别,对于内存管理这⼀块的知识点⼤家能看懂最好,不能看懂也没关系,后⾯我们会详述。存储类型到这⾥就是说完了,下⼀节将进⼊到运算符的学习。
上节作业分析
1.下列程序的输出结果是16.00,请填空
#include
int main()
{
int a = 9, b = 2;
float x = _____,y = 1.1, z;
z = a/2 + b*x/y + 1/2;
printf("%5.2f", z);
return 0;
}
已知a = 9,b = 2;z = 9/2 + 2*x/1.1 + 1/2;在C语⾔中,如果运算时,浮点型向整型进⾏强制转换时注意精度丢失的问题
怎么理解呢?定义的a和b是整数,9/2 = 4.5,但由于a是int型,得到的结果为整数,即4,⽽1/2则为0,所以z = 4+2*x/1.1 = 16,解⽅程得x = 6.6
2.以下程序运⾏后的输出结果是:( )
#include
#define S(x) 4*x*(x)+1
int main()
{
int i=6,j=8;
printf("%d",S(i+j));
return 0;
}
根据上⼀节我们说的,遇到这种宏定义问题要整体代⼊,S(i+j) = 4*i+j*(i+j)+1 = 4*6+8*(6+8)+1 = 137
本节作业
下⾯程序输出结果是什么?
温馨提⽰:第⼀节有⼀个很奇怪的链接,⼤家记得保存哦~
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论