关键字和声明
关键字
1. 数据类型关键字(12 个):
(1). char :声明字符型变量或函数 1个字节
(2). double :声明双精度变量或函数 8个字节
(3). enum :声明枚举类型
(4). float:声明浮点型变量或函数 4字节
(5). int: 声明整型变量或函数 4字节
(6). long :声明长整型变量或函数 32位 4字节 64位 8字节
(7). short :声明短整型变量或函数 2字节
(8). signed:声明有符号类型变量或函数
(9). struct:声明结构体变量或函数 注意内存对齐,比较复杂(后续祥谈)
(10). union:声明联合数据类型 内存大小以最大类型为主
(11). unsigned:声明无符号类型变量或函数
(12). void :声明函数无返回值或无参数,声明无类型指
针(基本上就这三个作用)
控制语句关键字(12 个)
:
A.循环语句(1). for: 一种循环语句(可意会不可言传)
(2). do : 循环语句的循环体
(3). while :循环语句的循环条件
(4). break:跳出当前循环 以及 switch 的 case 执行控制
(5). continue:结束当前循环,开始下一轮循环
B.条件语句
(1).if: 条件语句
(2).else :条件语句否定分支(与 if 连用)
(3).goto:无条件跳转语句
C.开关语句
(1).switch :用于开关语句
(2).case:开关语句分支
(3).default:开关语句中的“其他”分支
D.
return :子程序返回语句(可以带参数,也看不带参数)
3. 存储类型关键字(4 个):
(1).auto :声明自动变量 一般不使用
(2).extern:声明变量是在其他文件正声明(也可以看做
是引用变量)
(3).register:声明寄存器变量,提高运行效率
(4). static :声明静态变量
:
(1).const :声明只读变量
(2).sizeof:计算数据类型长度
(3).typedef:用以给数据类型取别名(当然还有其他作用)
(4).volatile:说明变量在程序执行中可被隐含地改变
声明 ,不允许机器优化
变量的声明和定义
声明:一个变量意味着向编译器描述变量的类型,但并不为变
量分配存储空间。
定义::一个变量意味着在声明变量的同时还要为变量分配存
储空间。
变量的声明有两种情况:
(1) 一种是需要建立存储空间的(定义、声明)。例如:int
a 在声明的时候就已经建立了存储空间。
(2) 另一种是不需要建立存储空间的(声明)。例如:
extern int a 其中变量 a 是在别的文件中定义的。前者是"定义性声明( defining declaration)"或者称为"定
义 (definition)", 而 后 者 是 " 引 用 性 声 明 (referncing
declaration)".从广义的角度来讲声明中包含着定义,但是并
非所有的声明都是定义,例如:int a 它既是声明,同时又是
定义。
然而对于 extern a 来讲它只是声明不是定义。一般的
情况下我们常常这样叙述,把建立空间的声明称之为"定义",
而把不需要建立存储空间称之为"声明".很明显我们在这里
指的声明是范围比较窄的,也就是说非定义性质的声明。
例如:在主函数中
int main()
{
extern int A; //这是个声明而不是定义,声明 A 是一个已
经定义了的外部变量
//注意:声明外部变量时可以把变量类型去掉如:extern
A;dosth(); //执行函数
}
int A; //是定义,定义了 A 为整型的外部变量(全局变量)
外部变量(全局变量)的"定义"与外部变量的"声明"是不
相同的,外部变量的定义只能有一次, 它的位置是在所有
函数之外,而同一个文件中的外部变量声明可以是多次的,
它可以在函数之内(哪个函数要用就在那个函数中声明)也可
以在函数之外(在外部变 量的定义点之前)。系统会根据外部
变量的定义(而不是根据外部变量的声明)分配存储空间的。
对于外部变量来讲,初始化只能是在"定义"中进行,而不是
在" 声明"中。所谓的"声明",其作用,是声明该变量是一个已
在后面定义过的外部变量,仅仅是在为了"提前"引用该变量
而作的"声明"而已。extern 只作 声明,不作定义。
其实还与程序在编译,链接时的(符号表)有关系
用 static 来声明一个变量的作用有二:
(1) 对于局部变量用 static 声明,则是为该变量分配的
空间在整个程序的执行期内都始终存在,即使局部变量
也可以延长生命作用域,它在在在内存中静态区,在加载
内存前,在磁盘的数据段(.data)
(2) 外部变量用 static 来声明,则该变量的作用只限于
本文件
隐形刺客:auto
1.
描述:auto 关键字在我们写的代码里几乎看不到,但是它又
无处不在,它是如此的重要,又是如此的与世无争,默默的
履行着自己的义务,却又隐姓埋名。
作用:C 程序是面向过程的,在 C 代码中会出现大量的函数
模块,每个函数都有其生命周期(也称作用域)
,在函数生
命周期中声明的变量通常叫做局部变量,也叫自动变量。例
如:
int fun(){
int a = 10;
// auto int a = 10;
/ / do something
return 0;
}
整型变量 a 在 fun 函数内声明,其作用域为 fun 函数内,出来 fun 函数,不能被引用,a 变量为自动变量。也就是说编
译器会有 int a = 10 之前会加上 auto 的关键字。
auto 的出现意味着,当前变量的作用域为当前函数或代码段
的局部变量,意味着当前变量会在内存栈上进行分配。
内存栈:
如果大家学过数据结构,应该知道,栈就是先进后出的数据
结构。它类似于我们用箱子打包书本,第一本扔进去大英,
第二本扔进行高数,第三本扔进行小说,那么取书的时候,
先取出来第一本是小说,第二是高数,第三本是大英。
栈的操作为入栈和出栈,入栈就是向箱子里扔书,出栈就是
从箱子里取书。那么这和我们的 auto 变量分配空间有什么关
系呢?
由于一个程序中可能会有大量的变量声明,每个变量都会占
有一定的内存空间,而内存空间对于计算机来说是宝贵的硬
件资源,因此合理的利用内存是编译器要做的一个主要任务。
有的变量是一次性使用的,如局部变量。有的变量要伴随着
整个程序来使用的,如全局变量。为了节省内存空间,优化
性能,编译器通常会将一次性使用的变量分配在栈上。也就
是说,代码中声明一个一次性变量,就在栈上进行入栈操作。
当该变量使用完了(生命周期结束)
,进行出栈操作。这样,
在执行不同的函数的时候,就会在一个栈上进行出入栈操作,
也就是说它们在频繁的使用一个相同的内存空间,从而可以
更高效的利用内存。
PS:有的编译器为了提高效率,在出栈时不会进行数据清空,
这也就意味着,下个函数里的变量在入栈使用该空间时,里
面的数据是上一次变量操作的结果。
2.
闪电飞刀:register
描述:register 就和它的名字一样,很少出现在代码世界中,
因为敢称为闪电飞刀的变量,通常只会在一些特定场合才能
出现。它是如此的快,以致于 CPU 都对其刮目相看,但是它
有一个致命的缺点,它的速度“看心情”而定,不是每一次
都能让人满意。
作用:如果一个变量被 register 来修辞,就意味着,该变量
会作为一个寄存器变量,让该变量的访问速度达到最快。比
如:一个程序逻辑中有一个很大的循环,循环中有几个变量
要频繁进行操作,这些变量可以声明为 register 类型。
寄存器变量:寄存器变量是指一个变量直接引用寄存器,也
就是对变量名的操作的结果是直接对寄存器进行访问。寄存
器是 CPU 的亲信,CPU 操作的每个操作数和操作结果,都
由寄存器来暂时保存,最后才写入到内存或从内存中读出。
也就是说,变量的值通常保存在内存中,CPU 对变量进行读
取先是将变量的值从内存中读取到寄存器中,然后进行运算,
运算完将结果写回到内存中。为什么要这么设计,而不直接
对变量的值从内存中进行运算,而要再借助于寄存器?这是
由于考虑到性能的问题才这么设计的。在计算机系统中,包
含有很多种不同类型的存储器,如表 xxx 所示。
表 xxx 计算机存储器分类
名称
速度
特点
静态存储器 最快 造价高,体积大,适合小容量的缓存
动态存储器 较快 造价较低,体积较小,适合大容易保存数据
在计算机中 CPU 的运算速度最快,
现在都达到 3GHZ 左右,
而相对应的存储器速度却相对慢很多,访问速度最快的寄存器和缓存,由于其体积又大,不适合大容量的使用,所以只
能二者相接合的方式来提高效率。程序代码保存在内存中,
当使用数据时,将其送到寄存器,让 CPU 来访问,使用完
毕,送回内存保存。而 C 语言又允许使用寄存器来保存变量
的值,很明显这样能大大提高程序的执行速度,但是,寄存
器的个数是有限的,X86 也就是十几个,
ARM 最多才 37 个。
我们不可能将全部的变量都声明为寄存器变量,因为其它代
码也要使用寄存器,同样,我们声明的寄存器变量也不一定
直接保存在寄存器中,因为寄存器可能全部都在被其它代码
占用。编译器只能是尽量的为我们的变量安排在寄存器中。
在使用寄存器变量时,请注意:
·
待声明为寄存器变量类型应该是 CPU 寄存器所能接受的类
型,意味着寄存器变量是单个变量,变量长度应该小于等于
寄存器长度
·
不能对寄存器变量使用取地址符“&”,因为该变量没有内存地
址
·
尽量在大量频繁的操作时使用寄存器变量,且声明的变量个
数应该尽量的少。