C语言变量作用域和存储方式

C语言变量作用域和存储方式

C语言中,每个变量各函数都有两个属性:数据类型(整型、浮点型等)和数据的存储类别(内存中的存储方式:静态存储、动态存储)。

定义和声明变量和函数时应同时指定数据类型存储类别,不指定系统会隐含指定某一存储类别。

“局部变量”和“全局变量”

变量按作用域可分为“局部变量”和“全局变量”

动态存储方式与静态存储方式

从变量值存在的时间(生存期) 分为:静态存储方式动态存储方式

  • 静态存储方式: 程序运行期间由系统分配的存储空间。
  • 动态存储方式:程序运行期间根据需要进行动态分配。

内存中供用户使用的存储空间如下,分为3个部分:
在这里插入图片描述

  1. 程序区
  2. 静态存储区:主要用于存放静态数据和全局数据。存储在静态存储区中的数据存在于程序运行的整个过程中。所以静态局部变量不同于普通局部变量,静态局部变量是存在于程序运行的整个过程中的。
    全局变量存储在静态存储区,程序开始时给全局变量分配存储区,程序执行完毕释放。
  3. 动态存储区:函数调用开始时分配动态存储空间,函数结束时释放这些空间。
    1. 函数形式参数。在调用函数时给形参分配的存储空间。
    2. 函数中定义的没有用关键字static声明的变量,即自动变量
    3. 函数调用时的现场保护和返回地址等。
      数据分别存放在静态存储区和动态存储区。

局部变量存储类别

自动变量(auto变量)

函数中的局部变量(未声明为static存储类别)、函数中的形参、函数体中定义的局部变量(包括复合语句中定义的局部变量),调用函数中分配存储空间,调用结束时自动释放。

int f(int a){
	auto int b,c = 3;
}

函数执行完自动释放a,b,c所占用的存储单元。auto关键字可以省略,默认指定为“自动存储类别”。

静态局部变量(static局部变量)

函数中的局部变量的值在函数调用结束后不消失而保留原值,其占用的存储单元不释放。用关键字static声明。

用 static 修饰过的局部变量称为静态局部变量。局部变量如果不用 static 进行修饰,那么默认都是 auto 型的,即存储在栈区。而定义成 static 之后就存储在静态存储区了。

int f(int a){
	auto int b = 0;
	static int c = 3;
	b = b + 1;
	c + c + 1;
	return (a + b + c)
}
  • 若局部变量不赋初值编译时自动赋值0或\0,自动变量的值是一个不确定的值。
  • 静态局部变量在函数调用后虽然存在,因其为局部变量,不能被其他函数引用,只能被本函数引用。

寄存器变量(register变量)

什么叫“寄存器”?我们知道,内存条是用来存储数据的,硬盘也是存储数据的,而在 CPU 内部也有一些用来存储数据的区域,即寄存器。寄存器是 CPU 的组成部分,是 CPU 内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。它同内存一样,只不过它能存储的数据要少得多。

为了提高代码执行的效率,可以考虑将经常使用的变量存储到寄存器中。比如循环变量和循环体内每次循环都要使用的局部变量。这种变量叫作寄存器变量,用关键字 register 声明。如
register int a;
不经常使用,不再介绍。

总结:

局部变量声明存储类型,是指定变量的存储区域(静态存储区或动态存储区),以及由此产生的生存期的问题。

全局变量存储类别

extern 变量是针对全局变量而言的。通过前面了解到,全局变量都是存放在静态存储区中的,所以它们的生存期是固定的,即存在于程序的整个运行过程中。

但是对于全局变量来说,还有一个问题尚待解决,就是它的作用域究竟从什么位置起,到什么位置结束。作用域是包括整个文件范围,还是只包括文件中的一部分?是在一个文件中有效,还是在程序的所有文件中都有效?

一般来说,外部变量是在函数的外部定义的全局变量,它的作用域是从变量的定义处开始,到本程序文件的末尾结束。在此作用域内,全局变量可以被程序中各个函数所引用。但是有时程序设计人员希望能扩展全局变量的作用域,如以下几种情况:

在一个文件内扩展全局变量的作用域

如果全局变量不在文件的开头定义,其有效的作用范围只限于定义处到文件结束。在定义点之前的函数不能引用该全局变量。如果出于某种考虑,在定义点之前的函数需要引用该全局变量,那么就在引用之前用关键字extern对该变量作“外部变量声明”,表示将该全局变量的作用域扩展到此位置,比如:
extern int a;
有了此声明就可以从“声明”处起,合法地使用该全局变量了。

#include <stdio.h>
int main(){
	int max();
	//把外部变量A,B,C的作用域扩展到从此处开始
	extern int A,B,C;
	scanf("%d %d %d",&A,&B,&C);
	printf("max is %d\n",max());
}
//定义外部变量A,B,C
int A,B,C;
int max(){
	int m;
	m = A > B ? A : B;
	if(C > m)
		m = c;
	return (m);
}

最好将外部变量的定义放在引用它的所有函数前,避免在函数中多加一个extern声明。

将外部变量的作用域扩展到其他文件

一个 C 程序可以由一个或多个 .c 文件组成。如果程序只由一个 .c 文件组成,那么使用外部变量的方法前面已经介绍了。如果程序由多个 .c 文件组成,那么如何在一个文件中引用另一个文件中定义的外部变量呢?

假如在 1.c中定义了全局变量“int a=10;”,如果 2.c 和 3.c 也想使用这个变量 a,而我们不能在 2.c 和 3.c 中重新定义这个 a,否则在编译链接时就会出现“重复定义”的错误。正确的做法是在 2.c 和 3.c 中分别用 extern 对 a 作“外部变量声明”,即在 2.c 和 3.c 中使用 a 之前作如下声明:
extern int a;
这样在编译和链接时,当编译器在 2.c 中遇到变量 a 的声明时就会知道它有“外部链接”,就会从其他文件中寻找a的定义,并将在另一文件中定义的全局变量a的作用范围扩展到本文件中。这样在本文件中也可以合法地使用外部变量 a 了。但是现在问大家一个问题:“以 2.c 为例,如果在 2.c 中对 a 进行多次声明,即写多个“extern int a;”,那么程序会不会有错?”答案是不会,C 语言中是允许多次声明的,但有效的只有一个。
文件1.c

#include <stdio.h>
int main(){
	int max();
	//把外部变量A,B,C的作用域扩展到从此处开始
	extern int A,B,C;
	scanf("%d %d %d",&A,&B,&C);
	printf("max is %d\n",max());
}
//定义外部变量A,B,C
int A,B,C;
int max(){
	int m;
	m = A > B ? A : B;
	if(C > m)
		m = c;
	return (m);
}

文件2.c

//将1.c中已定义的外部变量的作用域扩展到本文件
extern A;
int power(int n){
	int i,y = 1;
	for(i = 1; i < n; i++ ){
		y *= A;
	}
	return (y);
}

extern扩展过程:在编译时,先从本文件中找外部变量的定义,若找到,就在本文件中扩展作用域;如找不到,在连接是从其他文件中找外部变量定义。找到将作用域扩展到本文件,找不到就按出错处理。

与全局变量一样,同一个项目的不同 .c文件中也不能定义重名的函数。如果2.c3.c 想要使用1.c中定义的函数,那么也只需要在2.c3.c 中分别对该函数进行声明就可以了。即直接把1.c中对函数的声明拷贝过来就行了。

将外部变量的作用域限制在本文件中

通过在外部变量定义时添加static声明,使外部变量只限本文件引用,不能被其他文件引用。此类型变量称为静态外部变量

例 file1.c

static int A;
int main(){
...
}

例 file2.c

extern A;
void fun(int n){
	...
	//出错
	A = A * n;
	...
}

总结:

对全局变量,都是在编译时分配内存,都存储在静态存储区,声明存储类型的作用是变量作用域扩展问题。

static声明变量作用

  1. 对局部变量用static声明,把它分配在静态存储区,该变量在整个程序执行期间不释放,其所分配的空间始终存在。
  2. 对全局变量用static声明,该变量的作用域只限于本文件模块(即被声明的文件中)

变量存储类型总结

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值