C语言深度剖析
关键字auto-最宽容大度的关键字
变量的分类
代码块:用{ }括起来的区域
局部变量:包含在代码块中的变量,局部变量具有临时性,进入代码块,自动形成局部变量,退出代码块自动释放。
全局变量:在所有函数外定义的变量。全局变量具有全局性。
作用域概念:指的是该变量可以被正常访问的代码区域
#include <stdio.h>
int main()
{
int x=10;
if(x==10)
{
y=20;
printf("%d %d",x,y);//x,y均可打印
}
printf("%d %d",x,y);//y会报错
return 0;
}
局部变量:只在本代码块内有效
全局变量:整个程序运行期间都有效
生命周期
概念:变量从定义到被释放的时间范围,所谓的释放,是指曾经开辟的空间“被释放”
局部变量:进入代码块,形成局部变量(开辟空间),退出代码块,“释放”全局变量
全局变量:定义完成之后,程序运行的整个生命周期内,该变量一直有效
作用域VS生命周期
打个比方来说,有一位大富豪,从他出生到死亡所做的贡献,从时间的维度上来理解,我们可以说是生命周期,他所影响的范围可以叫做作用域,作用域更偏向于空间的维度来说
再来举个例子:
#include <stdio.h>
int g_val=20;
int main()
{
int g_val=100;
printf("%d",g_val);
return 0;
}
当局部变量和全局变量命名起冲突的时候,编译器会优先考虑局部变量,所以打印结果为100
可以理解为就近原则
总结
作用域:该变量的有效范围
生命周期:时间的概念,什么时候被开辟,什么时候被释放
auto相关
如何使用:一般代码块中定义的变量,即局部变量,都是auto关键词修饰的,不过一般都是省略的
默认所有的变量都是auto修饰的吗?
不是,一般用来修饰局部变量
局部变量,临时变量,自动变量统称为局部变量
auto关键字已经很老,永不使用,在C语言中,但是C++和这个不一样
关键字 register-最快的关键字
铺垫知识:
寄存器的本质
在硬件层面上,提高计算机的运算效率。因为不需要从内存中读取数据啦。
register修饰变量
尽量将所修饰的变量放到CPU寄存区中,从而达到提高效率的目的
那么什么样的变量可以用register
1.局部的(全局会导致CPU寄存器长时间被占用)
2.不会被写入的(写入就需要写回内存,后续还需要读取检测,那么register的意义何在?)
3.是高频被读取的(提高效率)
4.如果要使用,不是大量使用(寄存器数量有限)
#include <stdio.h>
int main()
{
register int a=10;
printf("%d\n",a);
return 0;
}
结果可以被正常打印,但是既然是存放在寄存器中,也就不是存储在内存中,所以不可以使用取地址符号&
关键字static-最名不副实的关键字
对extern声明的小小补充
当我要对一个函数进行声明的时候可不可以像如下情况:
extern int v_gal=100;
对这个变量进行了赋值,这是不可以的,因为声明并没有开辟空间,=100这是开辟空间或者初始化
所以我们得出结论:
所有的变量声明的时候不能设置初始值
再来将讲一点:
我们这里是main.c这个源文件去调用test.c里的show()函数,倘若还有test1.c,test2.c,test3.c要去调用这个show()函数呢,所以:
单纯地使用源文件,组织项目结构的时候,项目越大越复杂的时候,维护成本会变得越来越高
这样也就诞生了头文件 .h
.h:头文件,组织项目结构的时候,减少大型项目的维护成本
接下来是对维护成本的解释:
还是拿刚刚的例子来举例,如果说我们要把上面的v_gal改成v_gal2,那么我们是不是要把所有的源文件声明的位置进行改动,如果说漏掉一个,,都会导致程序运行错误,这里还好只有四个源文件,但是如果是四十个,或者四百个呢,你试想一下。
综上,我们都在回答一个问题:为什么要有头文件
有关头文件的补充说明:
.h基本上都是要被多个源文件包含的,可能有一个问题,头文件被重复包含的问题,会导致运行效率降低
解决方案:
在头文件开头写上#pragma once(**PS:**在VS2022中会默认加上#pragma once)
头文件包含以下内容:
-
C头文件
-
所有的变量的声明
-
所有的函数的声明
-
#define ,类型typedef, struct
在C语言中,包含头文件的两种形式:
#include <stdio.h>这种是C语言库里面要包含的头文件
#include"test.h"是包含自定义的头文件
这个地方我们要特别注意的是函数的声明,因为在链接的过程中,test.c和main.c会进行匹配看是否有show()函数,即使说你已经定义了该函数,但是你没有声明的时候,编译器会忽视,所以要进行声明
书写如下:
不向里面添加函数体,道理和声明变量一个道理
注意:
变量声明必须带上extern!!!
虽然在实际应用的时候编译器不会报错,但是你会无法区分是开辟空间还是声明变量
函数声明建议带上extern,为什么是建议呢。因为区别在于有没有函数体,编译器在识别的时候如果没有看到函数体会默认是函数的声明
几个小问题:
1.全局变量可以跨文件访问吗?可以
2.函数可以跨文件访问吗?可以
在具体的应用场景中,有没有可能我们不想让全局变量或者函数跨文件访问,指向本文件内部被访问
请出我们真正的主角-------static
看上面这幅图片,LNK表示的是链接的意思,这里是链接错误
static int g_val =100;//全局变量
访问吗?可以
在具体的应用场景中,有没有可能我们不想让全局变量或者函数跨文件访问,指向本文件内部被访问
请出我们真正的主角-------static
[外链图片转存中…(img-pPVbonaX-1723038243763)]
看上面这幅图片,LNK表示的是链接的意思,这里是链接错误
static int g_val =100;//全局变量
结论1:static修饰全局变量,该变量只能在本文件内被访问,不能被外部其他文件直接访问(可以被间接访问,如被函数调用)