C 存储类
存储类定义 C 程序中变量/函数的范围(可见性)和生命周期。这些说明符放置在它们所修饰的类型之前。下面列出 C 程序中可用的存储类:
- auto
- register
- static
- extern
auto 存储类
auto 存储类是所有局部变量默认的存储类。
{ int mount; auto int month; }
上面的实例定义了两个带有相同存储类的变量,auto 只能用在函数内,即 auto 只能修饰局部变量。
register 存储类
register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 '&' 运算符(因为它没有内存位置)。
{ register int miles; }
寄存器只用于需要快速访问的变量,比如计数器。还应注意的是,定义 'register' 并不意味着变量将被存储在寄存器中,它意味着变量可能存储在寄存器中,这取决于硬件和实现的限制。
static 存储类
static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。
static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。
全局声明的一个 static 变量或方法可以被任何函数或方法调用,只要这些方法出现在跟 static 变量或方法同一个文件中。
以下实例演示了 static 修饰全局变量和局部变量的应用:
实例
实例中 count 作为全局变量可以在函数内使用,thingy 使用 static 修饰后,不会在每次调用时重置。
可能您现在还无法理解这个实例,因为我已经使用了函数和全局变量,这两个概念目前为止还没进行讲解。即使您现在不能完全理解,也没有关系,后续的章节我们会详细讲解。当上面的代码被编译和执行时,它会产生下列结果:
thingy 为 6 , count 为 9 thingy 为 7 , count 为 8 thingy 为 8 , count 为 7 thingy 为 9 , count 为 6 thingy 为 10 , count 为 5 thingy 为 11 , count 为 4 thingy 为 12 , count 为 3 thingy 为 13 , count 为 2 thingy 为 14 , count 为 1 thingy 为 15 , count 为 0
extern 存储类
extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。当您使用 extern 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。
当您有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。可以这么理解,extern 是用来在另一个文件中声明一个全局变量或函数。
extern 修饰符通常用于当有两个或多个文件共享相同的全局变量或函数的时候,如下所示:
第一个文件:main.c
实例
第二个文件:support.c
实例
在这里,第二个文件中的 extern 关键字用于声明已经在第一个文件 main.c 中定义的 count。现在 ,编译这两个文件,如下所示:
$ gcc main.c support.c
这会产生 a.out 可执行程序,当程序被执行时,它会产生下列结果:
count is 5
冷锋SJ记忆
son***e_xuan@126.com
auto 是局部变量的默认存储类, 限定变量只能在函数内部使用;
register 代表了寄存器变量,不在内存中使用;
static是全局变量的默认存储类,表示变量在程序生命周期内可见;
extern 表示全局变量,即对程序内所有文件可见,类似于Java中的public关键字;
冷锋SJ记忆
son***e_xuan@126.com
势不可挡
911***607@qq.com
参考地址
C 语言中全局变量、局部变量、静态全局变量、静态局部变量的区别
从作用域看:
1、全局变量具有全局作用域。全局变量只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他不包含全局变量定义的源文件需要用extern 关键字再次声明这个全局变量。
2、静态局部变量具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行结束都一直存在,它和全局变量的区别在于全局变量对所有的函数都是可见的,而静态局部变量只对定义自己的函数体始终可见。
3、局部变量也只有局部作用域,它是自动对象(auto),它在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用执行结束后,变量被撤销,其所占用的内存也被收回。
4、静态全局变量也具有全局作用域,它与全局变量的区别在于如果程序包含多个文件的话,它作用于定义它的文件里,不能作用到其它文件里,即被static关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同名字的静态全局变量,它们也是不同的变量。
从分配内存空间看:
1、全局变量,静态局部变量,静态全局变量都在静态存储区分配空间,而局部变量在栈里分配空间
2、全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。
从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。因此static 这个说明符在不同的地方所起的作用是不同的。应予以注意。
Tips:
势不可挡
911***607@qq.com
参考地址
小军
198***0646@qq.com
参考地址
auto 普通局部栈变量,是自动存储,这种对象会自动创建和销毁 ,建议这个变量要放在堆栈上面,调用函数时分配内存,函数结束时释放内存。一般隐藏auto默认为自动存储类别。我们程序都变量大多是自动变量。
实例 auto.c
Register变量:动态和静态变量都是存放在内存中,程序中遇到该值时用控制器发指令将变量的值送到运算器中,需要存数再保存到内存中。如果频繁使用一个变量,比如一个函数体内的多次循环每次都引用该局部变量,我们则可以把局部变量的值放到CPU的寄存器中,叫寄存器变量。不需要多次到内存中存取提高效率。但是只能局部自动变量和形参可以做寄存器变量。在函数调用时占用一些寄存器,函数结束时释放。不同系统对register要求也不一样,比如对定义register变量个数,数据类型等限制,有的默认为自动变量处理。所以在程序一般也不用。
实例 register.c
输出结果:
小军
198***0646@qq.com
参考地址
FK
421***224@qq.com
参考地址
在 C 语言中,static 可以用来修饰局部变量,全局变量以及函数。在不同的情况下 static 的作用不尽相同。
(1)修饰局部变量
一般情况下,对于局部变量是存放在栈区的,并且局部变量的生命周期在该语句块执行结束时便结束了。但是如果用static进行修饰的话,该变量便存放在静态数据区,其生命周期一直持续到整个程序执行结束。但是在这里要注意的是,虽然用static对局部变量进行修饰过后,其生命周期以及存储空间发生了变化,但是其作用域并没有改变,其仍然是一个局部变量,作用域仅限于该语句块。
在用static修饰局部变量后,该变量只在初次运行时进行初始化工作,且只进行一次。
如:
程序执行结果为: 2 3
说明在第二次调用fun()函数时,a的值为2,并且没有进行初始化赋值,直接进行自增运算,所以得到的结果为3.
对于静态局部变量如果没有进行初始化的话,对于整形变量系统会自动对其赋值为0,对于字符数组,会自动赋值为'\0'.
(2)修饰全局变量
对于一个全局变量,它既可以在本源文件中被访问到,也可以在同一个工程的其它源文件中被访问(只需用extern进行声明即可)。
如:
则执行结果为 1
但是如果在 file1.c 中把 int a=1 改为 static int a=1;
那么在file2.c是无法访问到变量a的。原因在于用static对全局变量进行修饰改变了其作用域的范围,由原来的整个工程可见变为本源文件可见。
(3)修饰函数
用static修饰函数的话,情况与修饰全局变量大同小异,就是改变了函数的作用域。
FK
421***224@qq.com
参考地址
学以解忧
145***3462@qq.com
static 的用法
用来说明静态变量 ,如果是在函数的,那么其效果和全局变量类似 。但是,static定义的变量只能在当前 c 程序文件中使用,在另一个 c 代码里面 , 即使使用 extern 关键词也不能访问这个static变量。如果实在函数内部定义的,那么这个变量只初始化一次,即使再次调用这个函数,这个static变量也不会再次初始化 , 这个变量的取值就会一直保存着,也就是说,当你再次调用这个函数的时候,里面用到这个static变量时,就会发现,它还是上一次函数调用时的结果。
实例 static.c:
运行结果如下:
由此可见,用static修饰的局部变量只初始化一次。
学以解忧
145***3462@qq.com