C语言之变量的作用域与修饰关键字

变量的属性

  • 存储位置:变量使用的是哪一段内存
  • 作用域:变量的使用范围
  • 生命周期:创建时间~销毁时间

注意:作用域和生命周期要特别注意区分概念。

变量的作用域

全局变量:定义在函数外。
  • 存储位置:未初始化的存储在BSS段,被初始化的存储在DATA段

  • 作用域:整个程序。比如在a.c定义了全局变量,在b.c中也可以使用。

  • 生命周期:main函数执行前就被定义出,程序运行结束后再释放。

    注意:在程序中,局部变量和全局变量的名称可以相同,如果两个名字相同,会优先使用局部变量值,全局变量暂不可被引用。在同一个函数中不能定义具有相同名字的局部变量。

局部变量:定义在函数内。
  • 存储位置:栈
  • 作用域:所在的函数内
  • 生命周期:从定义语句开始~函数执行结束。函数每调用一次就进行一遍定义、释放。
块变量:定义在if,for,while等语句块中。
  • 存储位置:栈
  • 作用域:所在语句块的大括号内。
  • 生命周期:从定义语句开始~函数执行结束(注意不是对应的块结束时)。
    #include<stdio.h>
    void func(void)
    {
    	int* p = NULL;
    	for(int i =0; i<10;i++)  p = &i;
    	//printf("%d",i);			//超出了i的作用域,无法访问
    	printf("%d",*p);			//依然可以通过指针访问i地址的数据
    }
    
    int main()
    {
    	func();
    }
    
初始化局部变量和全局变量

当局部变量被定义时,系统不会对其初始化,您必须自行对其初始化。定义全局变量时,系统会自动对其初始化,如下所示:

数据类型初始化默认值
int0
char‘\0’
float0
double0
pointerNULL

修饰变量的关键字

auto:

用来定义申请内存、自动释放内存的变量(局部、块变量,默认被auto修饰)。申请和释放的都是访问权限,不是数据。
注意:auto只能用在函数内,即 auto 只能修饰局部变量。全局变量和static变量不能被auto修饰。因为它们的内存段不同。

const:

是对变量提供一种保护机制,但它不一定是常量。
const变量一旦初始化后,就不能再显式地修改它的值。但是可以通过指针来修改。
const修饰被初始化过的全局变量才是真正的常量,一旦修改就出现段错误,因为编译器把这种全局变量的存储位置划分进了内存的代码段。

#include<stdio.h>
const int num2;				//未初始化的全局变量
const int num3 =13;			//已初始化的全局变量
int main()
{
	const int num1 = 2;		//局部变量
//	num2 = 10;				//无法显式地修改const变量(const的作用就在于此)
	int* p1 = &num1;		
	*p1 = 10;				//但是可以通过指针间接地修改
	printf("num1 = %d\n",num1);

	int* p2 = &num2;		
	*p2 = 11;				//未初始化的全局变量也可通过指针修改
	printf("num2 = %d\n",num2);

	int* p3 = &num3;
//	已初始化的全局变量是真正意义上的常量。在编译时就存在于内存的代码段,只有只读权限,不允许任何形式的修改、赋值。
//	*p3 = 12;			
//	num3 =12;
}

注意:const int func(void); const 修饰的是函数的返回值

static:

存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。

  • 全局变量:限制全局变量的作用域,只能在当前文件内使用

  • 块、局部变量:改变存储位置,由栈改为BSS段或DATA段(由是否初始化决定),但作用域没有变。只执行初始化一次,并且会延长生命周期,直到程序运行结束以后才释放。。

    #include<stdio.h>
    void func()
    {
    	for(int i =0;i<5;i++)
    	{	
    		static int num = 0;			//只初始化一次
    		num++;
    		printf("%d ",num);
    	}
    }
    
    int main()
    {
    	func();
    }
    /*
    out:
    1 2 3 4 5 
    */
    
  • 修饰函数:

注意:static int func(void); static 修饰的是函数(由普通函数变为内部函数),只能在当前文件内调用。

register:

计算机的存储介质(从慢到快):硬盘 -> 固态硬盘 -> 内存 -> 缓存 -> 寄存器
register关键字申请把变量的存储位置更改为寄存器。仅仅是申请,因为寄存器数量有限或者硬件不同,不一定成功。
适用场景:如果要写一个死循环,其中有一个变量要频繁计算,那么就应该修饰为register,比如计数器。可以大大提高运算效率。

注意:寄存器变量不能取地址符‘&’(因为它没有内存位置)。

volatile:

(不稳定的,易变的):修饰线程间共享的变量,或者硬件编程时使用。
如果一个变量的值没有显式的修改,编译器不会再次从内存中读取它的数值,而是直接使用上次的读取结果(优化过程)。
volatile的功能就是告诉告诉编译器变量的值随时可能发生变化,不要优化它的取值过程(每次用到变量时都去内存中获取它的值)

int num = 10;
num  ==  num; 		//永远为真。
volatile int num1 = 20;
num1 == num1;  		//不一定为真,多线程或者硬件改变时。
extern:

多文件中共享全局变量时使用。谁使用谁声明。可以这么理解,extern 是用来在另一个文件中声明一个全局变量或函数。
定义的含义:创建变量名,分配存储空间
声明的含义:创建变量名
a.c中定义一个全局变量,b.c中如果想使用,共享一个变量。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值