一、前言-题外话-扩展-瞎说
C语言一共有多少关键字呢?一般的书上,都是32个(C90\C89)。C99又新增了5个关键字。
正题没开始之前先说点题外话 我们平时使用windows时的鼠标双击代表了什么? 不用动脑子就知道了,那就是启动程序。 那么启动程序的本质又是什么呢? 你们一定不知道吧,那我来告诉你 将程序数据(一般存在硬盘文件中),加载到内存中,让cpu读取运算。 那为什么要加载到内存中呢? 因为快,当cpu从内存中读取一定是比从硬盘中读取要快的多的,这也就是为什么内存比硬盘要贵的多的原因。 离CPU越近的存储单元,效率越高,单价成本越贵
我们使用的笔记本电脑,通过缓存技术,使得我们以便宜的价格,用到高效率的计算机(仅仅买了一点点cpu和内存)。

对于任何一种硬件而言,它充当了上一层硬件的缓存(这就是上文提到的缓存技术) 比如:内存是硬盘的缓存,因为硬盘里的数据一般先缓存到内存中。
至此,我们再来简单了解一下冯诺依曼体系结构 
二、定义与声明再讨论
学习了这么久C语言了,这里有一个问题,什么是变量?
答:在内存中开辟特定大小的空间,用来保存数据
这里我们得知道:定义(开辟空间)只能有一次;而声明可以有很多次
接着又有一个问题,为什么要定义变量?这个问题是不是很奇怪? 我来回答
计算机是为了计算,计算就需要数据。但是重点是,在计算的时候,任何一个时刻,不是所有数据都要立马被计算掉(这样效率是很低的,具体为什么低我也不知道)。 换句话说,为何需要变量?因为有数据需要暂时保存起来,等待后续处理。 再换句话说,就是数据从硬盘缓存到内存中,内存中的数据是一点点的被cpu拿去计算,这是需要变量把内存中的数据暂时存起来。总而言之这样是高效的。
那么可以得到变量定义的本质
在内存中开辟一块空间,用来保存数据。(为何一定是内存:因为定义变量,也是程序逻辑的一部分,程序已经被加载到内存中了)
既然有了变量定义的本质,那必然有变量声明的本质啦 就是声明告知啦,这里没什么想说的了,当然后面会更新extern,那个时候我会告诉大家
三、关键字
3.1最宽宏大量的关键字-auto
了解这个auto之前,我们先回顾一下变量的分类
- 局部变量:包含在代码块中的变量叫做局部变量(敲黑板新手注意了:不是说函数中的变量就是局部变量,这是不全面的,而是{ }中的变量)。局部变量具有临时性。进入代码块,自动形成局部变量,退出代码块自动释放。
- 全局变量:在所有函数外定义的变量。
我们再来谈谈变量的作用域 首先作用域的概念是:该变量可以被正常访问的代码区域。 局部变量在本代码块有效,全局变量在整个程序运行期间都有效,嗯,讲完了。 但这里需要注意一个小点: 局部变量和全局变量同名的时候,局部优先
作用域完了当然是生命周期 生命周期的概念:指的是该变量从定义到被释放(开辟的空间的释放)的时间范围。 局部变量: 进入代码块,形成局部变量(开辟空间),退出代码块,释放局部变量。 全局变量:定义完成之后,程序运行的整个生命周期内,该变量一直有效。
总结一下:声明周期是时间上的概念;作用域是可使用的有效区域。
—————————————————————— 回归正题:auto auto如何使用呢? 一般在代码块中定义的变量,也就是局部变量。默认都是auto修饰的,一般省略了。只能是修饰局部变量
这里我们来看一段代码,并回答一下问题 这里i用auto修饰可以吗?去掉j的auto可以吗?
int main()
{
for(int i = 0; i < 20;i++)
{
printf("%d\n",i);
if(1)
{
auto int j = 0;
printf("%d\n",j);
j+=1;
printf("%d\n",j);
}
}
return 0;
}
在vs2013运行这个程序的时候,报了一个这样的错误  解决方案: VS2010以前auto是指变量的存储类型,其它三种是:静态类型变量static、寄存器类型变量register和外部类型变量extern。 VS2010后auto语义发生变化,采用了C++语法,是类型推导之意。
解决方案: 把源文件换成.c 或者–》项目属性-C/C+±其他选项 增加/Zc:auto-即可。
当作者把源文件换成.c又报了一个链接错误  像我这种新手写个代码可不能心急,慢慢来。 解决方案(复制一段):
许多新手在编程时经常遇到“无法解析的外部符号 _main,该符号在函数 ___tmainCRTStartup 中被引用”这样的错误,最近看了一些这方面的书籍,现将解决方案大概叙述一下:
连接程序在负责连接可执行程序时,选择相应的c/c++运行时启动函数。如果设定了/subsystem:windows连接程序开关,那么连接程序会试图寻找WinMain或wWinMain函数。如果连个函数都不存在,那么就会返回一个“一个未解决的外部符号”(无法解析的外部符号 _main,该符号在函数 ___tmainCRTStartup 中被引用)
同样,如果设定了/subsystem:console连接程序开关,那么连接程序就会试图寻找main函数或者wmain函数,如果找不到这连个函数是,连接程序返回unresolved externel symbol错误信息。
通常新手容易犯的一个错误是,创建应用程序时选择了错误的应用程序类型。例如,开发人员创建了一个新的Win32应用程序项目,并给这个项目创建了一个入口函数main。在这种情况下,创建应用程序时,开发人员就会看到一个连接程序的错误信息。这是因为Win32应用程序项目设置了/subsystem:windows连接程序开关,但是却找不到相应的Winmain或者wWinmain函数。这时候你可以有以下几种解决方案。
1 将main函数改为Winmain函数
2 将/subsystem:windows开关改为/subsytem:console
3全部删除/subsytem:windows开关,让连接程序根据源代码中实现的函数进行正确的操作。
更改/subsystem:windows的方法:
右键点击项目,选择属性,会看到如下的选项框,点击连接器->系统,在右侧会看到“子系统”选项,在这里可以选择相应的连接程序开关。
我大概看了一下没看懂,所以果断重新创建一个项目试试。大概应该是这个意思
结果终于跑出来了:  和我们预期的一样,if代码块里面的代码没for循环一次,都是重新开辟。auto 加上和不加 效果是完全一样的(亲测)。 这里的i变量是属于for代码块里面的,也是一个局部变量。
——————————————————————
3.2-最快的关键字- register
其实,cpu主要负责计算的硬件单元,但是为了方便运算,一般第一步需要先把数据从内存读取到cpu内,那么也就需要cpu具有一定的数据临时存储能力。注意:cpu并不是当前要计算了,才把特定数据读到cpu里面的,那样太慢了。
所以现代cpu内,都集成了一组叫做寄存器的硬件,用来做临时的数据保存。
寄存器存在的本质:在硬件层面上,提高计算机的运算效率。因为不需要从内存中读取数取啦。
register修饰变量 尽量将所修饰变量,放入cpu寄存器中,从而达到提高效率的目的。
这里的加黑“尽量”是指,如果你一直给变量修饰上register,把它放在寄存器中,那总会有寄存器满了的情况,这时,系统不会再把变量用register修饰,也不会报错。你这时候用register修饰的变量可能已经自动放到内存里了。
那么什么样的变量最好用register修饰呢?
- 局部变量(全局变量会导致CPU寄存器长时间被占用)
- 不会被写入的变量(当我们写入数据时,就需要把寄存器上的变量载回内存,再进行修改,再写入cpu计算,那register完全失去了意义)
- 高频被读取的变量
- 请不要大量使用,因为寄存器的数量太有限了。
- register修饰的变量不能取地址(地址的概念是有关内存的,变量在寄存器中当然没有地址啦QaQ)
今日的两个关键字 auto 和register ,我们只需要记得他们存在就好了,写程序时候不用管,现在的编译器可以自动优化指定register。auto完全可有可无好吗?
|