目标:
初步了解关键字分类深刻理解变量深刻理解定义与声明auto关键字的理解站在存储结构角度,理解register关键字
目录
1.关键字分类
2.第一个C程序(补充内容)
3.变量的定义和声明
3.1 什么是变量
3.2 怎么定义变量
3.3 为什么要定义变量
3.4 变量定义与声明的差别
4.最宽宏大量的关键字---auto关键字
4.1 变量的分类
4.2 变量的作用域
4.3 变量的生命周期
4.4 作用域VS生命周期
4.5 auto相关
5. 最快的关键字-register
5.1存储金字塔
5.3 寄存器存在的本质
5.4 register修饰变量
1.关键字分类
2.第一个C程序(补充内容)
#include<stdio.h>#include<Windows.h>/*在编译的时候,把文本代码 --> 可执行程序(二进制文件)->windows下双击可以执行文件*///编译执行 就会生成解决方案,清理解决方案 生成的那些文件就没了int main(){printf("hello world\n");system("pause");//如果用VS 不会自动停屏,需要用system防止程序一闪而过return 0;}
扩充知识:
1.我们写出来的代码是文本代码,而点击编译执行的时候,编译器会把文本代码转化为二进制文件
也就是.exe(可执行程序),而要找到这个文件,只需要打开当前文件夹下的Debug文件夹
如图:
而双击.exe就会运行刚才我们所写的代码:
如果点击清理解决方案,那么观察文件夹 发现什么都没了!
2.
Windows当中,双击程序本质就是运行程序。那么运行程序的本质又是什么呢?
运行程序的本质就是将程序加载到内存当中
任何程序在运行之前都必须要先加载到内存当中
夺命二连问:
① 为什么程序在运行之前必须先加载到内存当中?
CPU和内存交互比较快,与硬盘交互慢--- 快!
(冯诺依曼硬件体系结构规定的必须先加载到内存中)
② 程序在被加载到内存之前,他在哪?
程序没有被加载的时候,在硬盘当中
这里需要用画图说明一下:
冯诺依曼体系结构:
3.变量的定义和声明
3.1 什么是变量
变量就是在内存中开辟特定大小的空间,用来保存数据
所有的变量,本质都是在内存中的某个位置开辟空间的!
那么变量可以在硬盘中开辟吗?
不可以!因为变量是程序运行的时候进行开辟的,而程序运行的时候,已经被加载到内存中了
所以变量一定是在内存中的!
而为什么是某个位置,因为我们是不知道的,是由操作系统随机分配的一个位置
3.2 怎么定义变量
定义变量的时候初始化char c='a';double d=3.14;
这种定义方式是开辟空间的时候,所开辟的空间的里直接放入内容(变量与生俱来的)
定义好变量,然后再赋值
char c;c='d';
这种定义方式是先开辟号一个空间 也就是变量c
然后 把d放到已经存在的空间里面
这两种定义方式没有本质的区别,这里只有在C语言的结构体部分才会有一些明显差别
3.3 为什么要定义变量
首先我们要知道,计算机是为了解决人类计算能力不足而产生的,也就是计算机是为了
进行计算的。
而计算就需要数据,但是计算过程中并不是所有的数据都立马需要被计算,有一些数据是需要先保存起来等待后续的处理的,所以利用变量是为了暂时保存数据
硬盘中的数据被加载到内存当中之后,是一次加载了很多数据,但是CPU一次只会处理一个数据!所以没有被CPU处理的数据就需要暂时存储起来,以便后续的处理
3.4 变量定义与声明的差别
定义:开辟空间
声明:更多的是一种告知,告知编译器某个变量是已经被定义好的,不用考虑它是不是没有被定义,等到后面链接的时候,把所有内容和我的变量关联起来就好了
注意:
定义只能有一次 (只能开辟一次空间)声明可以有多次
举个例子:表白只能表白一次,表白成功之后,你可以给多个人声明一下这是我的女朋友😛
4.最宽宏大量的关键字---auto关键字
4.1 变量的分类
局部变量:包含在代码块中的变量叫做局部变量。局部变量具有临时性。进入代码块,自动形成局部变量,退出代码块自动释放。(有很多说函数中的变量是局部变量,其实是不准确的)
全局变量:在所有函数之外定义的变量(不初始化默认为0),叫做全局变量。全局变量具有全局性
代码块:用{ }括起来的区域叫做代码块
更深入的: 关于程序地址空间和函数栈帧问题 会在后面具体讨论!
4.2 变量的作用域
局部变量的作用域:本代码块中{ } ,出作用域就会未定义标识符!
全局变量的作用域:整个程序运行期间都有效
4.3 变量的生命周期
生命周期概念:指的是变量从定义到释放的时间范围(强调的是时间),而作用域是指某个变量从什么地方开始有效到什么地方开始无效,强调的是空间。所谓的释放,指的是曾经开辟的空间“被释放”
局部变量:进入代码块,形成局部变量(开辟空间),退出代码块,“释放”局部变量
全局变量:定义完成之后,程序运行的整个生命周期内,该变量一直有效
4.4 作用域VS生命周期
区分生命周期和作用域!完全不同的概念
举个例子:
一个人从出生到死亡 ---生命周期
一个人对某一片区域做出贡献,产生影响 ----作用域
如果全局变量和局部变量名字相同---(冲突)
那么以局部变量优先的原则
如下图:
总结:
4.5 auto相关
如何使用?
一般在代码块中定义的变量,即局部变量,默认都是auto修饰的,不过一般省略
默认所有的变量都是auto吗?NO! 一般用来修饰局部变量
还有 一般我们提到的局部变量,自动变量,临时变量 都是一回事,我们统称为局部变量
auto 一般加在局部变量的前面,用来修饰局部变量,意味着这个变量只在该代码块内有效,出代码块自动销毁,不过auto关键字很老,现在默认省略
而auto修饰全局变量 会出错!(不能修饰全局变量)
5. 最快的关键字-register
其实 CPU主要是负责进行计算的硬件单元,但是为了方便运算,一般第一步需要先把数据从内存
中读取到CPU里面,那么也就需要CPU有一定的数据临时存储能力。注意:CPU并不是当前要计算了才把特定的数据读到CPU里,那样太慢了
所以现代CPU,都集成了一组叫做寄存器的硬件,用来做临时数据的保存
5.1存储金字塔
5.3 寄存器存在的本质
在硬件层面:提高计算机的运算效率。因为不需要从内存里读取数据了!
寄存器实际上就是一种缓存技术,利用Cache局部性原理,提前读取内存中的内容加载到寄存器当中,这样再访问数据的时候,会提升很大的速度
百度云盘之类的云盘 也应用了 缓存技术
5.4 register修饰变量
尽量将所修饰变量,放入CPU寄存器中,从而达到提高效率的目的
那么什么样的变量,可以采用register呢?
1.局部的(全局变量会导致CPU寄存器被场所及见占用)
2.不会被写入的(写入就需要写回内存,后续还要读取检测的话,register的意义在哪呢?)
3.高频被读取的(提高效率所在)、
4.如果要使用,不要大量使用,因为寄存器的数量有限
注意:被寄存器关键字修饰的变量 没有办法取地址(因为没有地址)
只有内存中才会有地址,寄存器是在寄存器中的,已经找到了还需要寻址吗?
#include<stdio.h>int main(){register int a=0;printf("&a=%p\n",&a);//编译器报错: 1 error c2103:寄存器上的变量"&"//注意:并不是所有的编译器会报错a=10;//寄存器变量可以被写入!只是register就没有意义了return 0;}
还有一个问题:如果寄存器定义的变量很多 会怎么办?
这里register 只是尽量把变量放到寄存器中,所以如果定义太多,他不会给你放进去,
并且编译器也会检查这个变量值不值得放到寄存器里。