c语言关键字
关键字就是已被C语言本身使用,不能作其它用途使用的字。例如关键字不能作变量名、函数名等。c语言关键字一共有32个。
基本数据类型5个
void
声明函数无返回值或无参数,声明无类型指针,显式丢弃运算结果。
char
字符型类型数据,属于整型数据的一种。
int
整型数据,通常为编译器指定的机器字长。
float
单精度浮点型数据,属于浮点数据的一种。
double
双精度浮点型数据,属于浮点数据的一种。
类型修饰关键字4个
short
修饰int,短整型数据,可省略被修饰的int。
long
修饰int,长整型数据,可省略被修饰的int。
signed
修饰整型数据,有符号数据类型。
unsigned
修饰整型数据,无符号数据类型。
复杂类型关键字5个
struct
结构体声明
union
共用体声明
enum
枚举声明
typedef
声明类型别名
sizeof
得到特定类型或特定类型变量的大小。
跳转结构4个
return
用在函数体中,返回特定值(或者是void值,即不返回值)。
continue
结束当前循环,开始下一轮循环。
break
跳出当前循环或switch结构。
goto
无条件跳转语句。
循环结构3个
for
for循环结构
do
do循环结构
while
while循环结构
分支结构5个
if
条件语句,后面不需要放分号
else
条件语句否定分支(与if连用)。
switch
开关语句(多重分支语句)。
case
开关语句的分支标记。
default
开关语句中的“其他”分支,可选。
存储级别关键字6个
auto
指定为自动变量,由编译器自动分配及释放。通常在栈上分配。
static
指定为静态变量,分配在静态变量区,修饰函数时,指定函数作用域为文件内部。
在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条。
先来介绍它的第一条也是最重要的一条:影藏。
当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。
register
指定为寄存器变量,建议编译器将变量存储到寄存器中使用,也可以修饰函数形参,建议编译器通过寄存器而不是堆栈传递参数。
extern
指定对应变量为外部变量,即标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。
在用C语言编写程序的时候,我们经常会遇到这样一种情况:希望在头文件中定义一个全局变量,然后包含到不同的c文件中,希望这个全局变量能在两个文件中共用。
当然,这样是不对的,编译时就会报错:error:symbol key multiply defined。也就是说编译器认为我们重复定义了key这个变量。因为#include命令呢,就是原封不动的把头文件中的内容搬到#include的位置,所以相当于所有的.C文件都执行了一次int key,而在C语言中全局变量是项目内(或者叫工程内)可见的,这样就造成了一个项目中多个变量key,编译器就认为是重复定义。
正确方法是:使用extern关键字来声明变量为外部变量。
变量定义:数据类型+变量名称,编译器需要给它分配内存单元的;
变量声明:extern数据类型+变量名称,是告诉编译器我这个变量将在其他外部c文件中定义,我这里只是外部用它。编译器就不给他分配内存空间,而等到真正遇到变量定义的时候再给他分配内存空间。
const
为什么下面的例子使用一个const变量来初始化数组,ANSIC的编译器会报告一个错误呢?
const int n=10;
int a[n];
答案与分析:
这个问题讨论的是“常量”与“只读变量”的区别。常量,例如5,“abc”等,肯定是只读的,因为常量是被编译器放在内存中的只读区域,这当然不能修改它。而“只读变量”则是在内存中开辟一个地方来存放它的值,只不过这个值由编译器限定不允许被修改。C语言关键字const就是用来限定一个变量不允许被改变的修饰符qualifier。上述代码中n被修饰为只读变量,可惜再怎么修饰也不是常量。而ANSI C规定数组定义时长度必须是“常量”,“只读变量”也是不可以的。
但是在标准C++中,这样定义的一个常量,这种写法是对的。实际上,根据编译过程及内存分配来看,这种用法本来就应该是合理的,只是ANSI C对数组的规定限制了它(实际上用GCC和VS2005编译以上代码,确实没有错误产生,也没有给出警告)。
那么,在ANSI C中用什么来定义常量呢?答案是enum和#define宏,这两个都可以用来定义常量。
另外注意,const只修饰其后的变量,至于const放在类型前还是类型后并没有区别。
volatile
volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。
需要注意的是,没有volatile也可能能正常运行,但是可能修改了编译器的优化级别之后就不能正常运行了。因此经常会出现debug版本正常,但是release版本却不能正常的问题。所以为了安全起见,只要是等待别的程序修改某个变量的时候,就加上volatile关键字。
易变的volatile
volatile的本意是“易变的”,由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。
一般来说volatile用在如下的几个地方:
中断服务程序中修改的供其它程序检测的变量需要加volatile。
多任务环境下各任务间共享的标志应该加volatile。
存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能有不同意义。
另外,以上几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计。
volatile的含义
volatile总是与优化有关,编译器有一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可以死代码消除。但有时这些优化不是程序所需要的,这时可以用volatile关键字禁止做这些优化。