在前面的20多章节里,我们学习了C语言全部的语法,下面我们将深度地剖析C语言知识。
目录
- 一.关键字的分类
- 二.第一个C语言程序
- 三.定义与声明
-
- 1.变量的定义
- 2.变量的声明
- 四.最宽宏大量的关键字---auto
-
- 1.变量的分类
- 2.变量的作用域
- 3.变量的生命周期
- 4.作用域VS生命周期
- 5.auto关键字
- 五.最快的关键字---register
-
- 1.必备知识
- 2.寄存器
- 3.register关键字
一.关键字的分类
在C语言中,C90标准下有32个关键字。但是在C99标准下,有37个关键字(增加了5个关键字)。不过有些主流的编译器不支持C99的标准,所以下面我们会讲述C90标准下的32个关键字。下面是32个关键字的图表总结:
关键字名称 | 关键字说明 |
---|---|
auto | 声明自动变量 |
short | 声明短整型变量或函数 |
int | 声明整型变量或函数 |
long | 声明长整型变量或函数 |
float | 声明浮点型变量或函数 |
double | 声明双精度变量或函数 |
char | 声明字符型变量或函数 |
struct | 声明结构体变量或函数 |
union | 声明共用体数据类型 |
enum | 声明枚举类型 |
typedef | 用以给数据类型取别名 |
const | 声明只读类型 |
unsigned | 声明无符号整型变量或函数 |
signed | 声明有符号整型变量或函数 |
extern | 声明外部变量或函数 |
register | 声明寄存器变量 |
static | 声明静态变量 |
volartile | 说明变量在程序执行中可被隐含地改变 |
void | 声明函数无返回值或参数,声明无类型指针 |
if | 条件语句 |
else | 条件语句否定分支 |
switch | 用于开关语句 |
case | 开关语句的分支 |
for | 一种循环语句 |
do | 循环语句的循环体 |
while | 循环语句的循环条件 |
goto | 无条件跳转语句 |
continue | 结束当前循环,开始下一轮循环 |
break | 跳出当前循环 |
default | 开关语句的其它分支 |
sizeof | 计算数据类型的长度 |
return | 子程序的返回语句\n |
上述图表便是C90标准的32个关键字,以后的关键字章节会进行集中详细的介绍。尽情期待!\
二.第一个C语言程序
c
#include <stdio.h>
int mian ()
{
printf("hello world!");
return 0;
}
上述程序是我们写的第一个C语言程序,让我们一起回顾一下吧!
当我们想要运行程序的时候,有许多种方法供我们使用。可以直接点击编译器的运行代码的选项;也可以在项目列表中,找到代码生成的二进制可执行程序,双击进行程序的运行。所以在这里,我们的角色就是写代码的程序员,编译器的角色是把文本代码变成二进制的可执行程序。
双击?不就是Windows下启动程序的做法吗?(我们玩游戏不就是双击桌面上的游戏图标吗?)。在程序没有被加载时,程序会被储存在硬盘中。所以说启动程序的本质就是:将程序数据加载到内存中,让计算机开始运行。
为什么运行程序要先将程序加载到内存中呢?因为:CPU无法直接访问硬盘数据,只能读取和运算内存中的数据。而程序默认存储在硬盘、U盘、外存上。外存的读写速度远远无法匹配CPU的运算速度,加载到内存是为了让程序能被CPU高效执行。举个简单的例子:外存就像家里的仓库用来长期存放程序(书籍)。内存就像书桌,CPU(你)只能在书桌上翻越书籍,处理内容。所以阅读书籍之前,必须把仓库的程序加载到书桌(内存)上。
三.定义与声明
1.变量的定义
在以前的学习中,我们了解了如何定义变量,下面我们复习一下吧。
c
int x= 10;
char c= 'a';
double d= 3.14;
像上述代码那样就是变量的创建方法:类型+变量名=默认值。
所有创建的变量都会在内存中开辟空间。但是我们为什么要创建这些变量呢?
原因:计算机是为了解决人们计算能力不足的问题而诞生的,即:计算机是用来计算的。而计算就需要相关的数据。但是计算机也不是所有的数据要马上处理。比如:数据1今天要处理,数据2想要先存着明天再进行处理。通过这个例子,我们可以得出结论:数据需要暂时被保存起来,等待后续处理。这就是创建变量的作用和核心。
变量定义的本质:程序运行时,变量需要加载到内存中去。程序计算时,就会使用到这些创建好的变量。所以定义变量的本质就是:在内存中开辟一块空间,用来保存数据。(为何一定是内存:因为定义变量,也是程序逻辑的一部分。程序此时已经被加载到内存中了)。
2.变量的声明
变量声明会用到关键字extern。所以下面只进行粗略的讲解。后面讲解extern关键字时,再详细说明。变量声明的核心是告诉编程语言这个变量名字代表一个可存储相关数据类型的数据的空间。下面举有关变量声明和定义区别的例子:
有一个宿舍有6个男孩子,同时喜欢一个女孩子。但是你经过很久的努力,通过浪漫的表白,成功获得了女孩的芳心。和女孩子(小红)成功成为了情侣。然后你因为爱激发出对女孩的占有欲,你便给其他5名舍友说:"小红现在是我的女朋友了,你们以后记得保持距离。"在这个例子里面,你的表白相当于变量的定义,而对舍友的警告相当于对变量的声明。
变量的定义只可有一次,而变量的声明可以有很多次。变量的声明是告诉编译器,该变量存在(只说不做),变量的定义是为变量分配内存并且初始化(又说又做)。变量的定义一定包含声明的作用,但是变量的话声明不一定包含定义的操作。
四.最宽宏大量的关键字---auto
1.变量的分类
在C语言中,变量分为局部变量和全局变量。
局部变量包含在代码块中,局部变量具有临时性,进入代码块时,自动形成局部变量,退出代码块自动释放。
全局变量是在所有函数外定义的变量。全局变量具有全局性。
下面给出相关例子的举例:
注释:代码块指的是用{ }括起来的区域。
c
#include <stdio.h>
int g =100;
int main()
{
int x = 10;
printf("x:%d" ,x);
printf("g:%d" ,g);
return 0;
}
上述代码中,g是全局变量。x是局部变量。调用printf函数会成功打印两变量初始化的值。
2.变量的作用域
作用域的概念:该变量可以被正常访问的代码区域。下面是代码例子:
c
//代码一
#include <stdio.h>
int main()
{
int x = 10;
if(x==10)
{
int y = 20;
printf("局部:x:%d,y:%d",x,y);//y只能在本代码块内有效
}
printf("局部:x:%d,y:%d",x,y);//报错,y不能被访问
return 0;
}
上述代码的具体解释:代码首先在大括号的外面创建了全局变量x,并且初始化为10,然后在大括号内部创建局部变量y,并且初始化为20。
在代码中,两次调用printf函数,第一次会成功打印,因为该次函数调用在局部变量y的作用域内,而第二次调用打印函数会保错,原因是局部变量y已经被内存释放(不在局部变量作用域内,使用该局部变量的行为是错误的)。
c
//代码二
# include <stdio.h>
int g = 100;//全局变量
void show()
{
printf("show:全局:%d",g);//在任何代码块中都可以被访问
}
int main()
{
show();
printf("main:全局:%d",g);//在任何代码块都可以被访问,甚至被修改。
}
上述代码的具体解释:首先创建了全局变量g并且初始化为100,并且分别在不同代码块进行该变量的访问。因为全局变量具有全局性,所以代码打印函数的调用不会保错,属于正确操作。
c
//代码三
#include <stdio.h>
int g = 100;//全局变量
int main()
{
int g = 10;//局部变量
printf("g:%d",g);//输出的是局部,当全局变量和局部变量数据冲突时,优先选用局部变量的数值。所以不建议类似此代码的写法。
return 0;
}
上述代码的具体解释:代码首先创建了全局变量g,并且初始化为100。但是在主函数内部,又一次进行g的定义。根据C语言的标准:当全局变量和局部变量数据冲突时,优先选用局部变量的数值。
3.变量的生命周期
变量生命周期的概念:该变量从定义到释放的时间范围。所谓的释放,指的是曾经开辟的空间被释放。
局部变量的生命周期:进入代码块,形成局部变量(此时为该变量开辟空间),退出代码块,释放局部变量。
全局变量的生命周期:定义完成之后,程序运行的整个生命周期内,该变量一直都有效。
4.作用域VS生命周期
变量的作用域和生命周期的核心区别:作用域是:变量能够被访问的代码范围(空间维度)。生命周期:变量从创建到创建到销毁的时间范围(时间维度)。
5.auto关键字
auto关键字的使用:一般在代码块中定义的变量,即:局部变量,默认都是auto关键字修饰的。不过该关键字一般省略不写。所以可以得出结论:auto关键字不是修饰所有的变量,而只是修饰局部变量。
注释:局部变量、自动变量和临时产量是一回事,以后均称为局部变量。
c
# include <stdio.h>
int main()
{
for (int i=0;i<10;i++)
{
printf("i=%d",i);
if(1)
{
auto int j=1;//自动变量
printf("before:j=%d;",j);
j++;
printf("after:j=%d",j);
}
}
return 0;
}

上述代码的具体解释:因为j是局部变量,所以进入j变量所在的代码块时,j的值会一直被重置,所以会出现1 2循环的现象。
五.最快的关键字---register
1.必备知识
CPU主要是负责进行计算的硬件单元,但是为了方便计算,一般第一步首先要把数据从内存中读取到CPU内。那么也就需要CPU具有一定的数据临时存储能力。注意:CPU并不是当前要计算了,才把特定的数据读到CPU里面,那样有个缺点就是太慢了。所以现代的CPU内,都集成了一组叫做寄存器的硬件,用来临时数据的保存。
2.寄存器
寄存器核心是CPU内部超高速的临时存储单元,作用是暂存CPU即将计算的数据和指令,避免CPU频繁读取速度较慢的内存,寄存器是连接CPU运算核心与内存的关键桥梁,直接决定CPU的运算效率。
不同的寄存器分工明确,共同支撑CPU的运算工作,核心类型包括:①数据寄存器:暂存CPU即将运算或运算后的原始数据。②指令寄存器:存放CPU正在执行的指令,让CPU运算核心明确下一步的操作。③程序计数器:存放下一条要执行的指令在内存中的地址,确保CPU能够按顺序依次执行指令,避免流程混乱。④地址寄存器:暂存要读取或写入的内存地址,相当于CPU给内存发定位,告诉内存要操作的数据在哪个位置。
通过上述解释,寄存器的本质作用是提高计算机的运算效率,原因是不需要从内存里读取数据了。
3.register关键字
该关键字的作用是:尽量将所修饰的变量放入CPU寄存区中,从而达到提高效率的目的。
register关键字可以修饰的变量:局部变量(全局变量会导致CPU寄存器被长时间占用)、不会被写入的(写入就需要写回内存,后续还要读取检测)、高频被读取的(提高读取效率)。
注意:
1.如果要使用该关键字,不要大量使用,因为寄存器的数量有限。并且需要注意的是该关键字是"尽量"将修饰的关键字放入CPU寄存器中,而不是一定会放入
2.不能对被register修饰的变量进行取地址操作,因为此时的变量只是放在了CPU寄存器上,并在内存中,所以对其取地址的行为是错误的。