C语言之关键字

C语言随读笔记 2013.11.09 小雨

一. C语言的标示符与关键字
关键字:编程语言保留的特殊标示符,有时又称为保留字;
标示符:表示源程序中某个对象的名字,最长255个字符;

关键字分类
32个关键字每个都有不同的意义,大体上根据其意义可以分为以下几类(下划线表示不同分类中有交集):

1) 非常见:auto、register、volatile、goto
2) 存储相关:const、extern、register、volatile、static、auto、signed、unsigned
3) 数据类型:char、short、int、float、long、double、struct、union、enum、void
4) 逻辑控制:if、else、for、while、do、break、continue、return、default、switch、case、goto
5) 特殊用途:sizeof、typedef

1. 隐形刺客:auto (auto--用以说明局部变量,默认值为此)

描述:auto关键字在我们写的代码里几乎看不到,但是它又无处不在,它是如此的重要,又是如此的与世无争,
默默的履行着自己的义务,却又隐姓埋名。
作用:C程序是面向过程的,在C代码中会出现大量的函数模块,每个函数都有其生命周期(也称作用域),在
函数生命周期中声明的变量通常叫做局部变量,也叫自动变量。例如:

例如:int fun()
{
int a = 10; //auto int a = 10;
//do someting
return 0;
}
说明:整型变量a在fun函数内声明,其作用域为fun函数内,出来fun函数,不能被引用,a变量为自动变量。也就
是说编译器会有int a = 10之前会加上auto的关键字。
2. 闪电飞刀:register

描述:register就和它的名字一样,很少出现在代码世界中,因为敢称为闪电飞刀的变量,通常只会在一些特定场
合才能出现。它是如此的快,以致于CPU都对其刮目相看,但是它有一个致命的缺点,它的速度“看心情”而定,
不是每一次都能让人满意。

作用:如果一个变量被register来修辞,就意味着,该变量会作为一个寄存器变量,让该变量的访问速度达到最快。
比如:一个程序逻辑中有一个很大的循环,循环中有几个变量要频繁进行操作,这些变量可以声明为register类型。

例如:#ifdef NOSTRUCTASSIGN

  memcpy (d, s, l)
  {

register char *d;
   register char *s;
   register int i;
   while (i--)
   *d++ = *s++;
  }

  #endif
说明:需要注意的地方
1) register变量必须是能被CPU寄存器所接受的类型,这通常意味着register变量必须是一个单个的值,并且其长度应小于
或等于整型的长度。但是,有些机器的寄存器也能存放浮点数
2) register变量可能不存放在内存中,所以不能用取址符运算符“ & ”
3) 只有局部变量和形参可以作为register变量,全局变量不行
4) 静态变量不能定义为register

3. volatile 该变量在程序执行中可被隐含地改变

volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,
都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,
如果这个变量由别的程序更新了的话,将出现不一致的现象。下面举例说明。在DSP开发中,经常需要等待某个事件的触发,所
以经常会写出这样的程序:
short flag;
void test()
{
do1();
while(flag==0);
do2();
}

这段程序等待内存变量flag的值变为1(怀疑此处是0,有点疑问,)之后才运行do2()。变量flag的值由别的程序更改,这个程
序可能是某个硬件中断服务程序。例如:如果某个按钮按下的话,就会对DSP产生中断,在按键中断程序中修改flag为1,这样上
面的程序就能够得以继续运行。但是,编译器并不知道flag的值会被别的程序修改,因此在它进行优化的时候,可能会把flag的
值先读入某个寄存器,然后等待那个寄存器变为1。如果不幸进行了这样的优化,那么while循环就变成了死循环,因为寄存器的
内容不可能被中断服务程序修改。为了让程序每次都读取真正flag变量的值,就需要定义为如下形式:
volatile short flag;
需要注意的是,没有volatile也可能能正常运行,但是可能修改了编译器的优化级别之后就又不能正常运行了。因此经常会出
现debug版本正常,但是release版本却不能正常的问题。所以为了安全起见,只要是等待别的程序修改某个变量的话,就加上volatile关键字。

4. goto 构成goto转移结构

描述:在所有的编程语言里,恐怕没有哪个关键字可以和goto相比,它可以指哪打哪,完全不用去顾忌编码规则,在代码世界里游刃有余,
混得代码海洋里的浪里白条美誉,也正是由于其放荡不羁的特性,被编码规则牢牢划死在编程准则不允许之首。

作用:正如其名,go to everywhere,它可以在代码逻辑中任意穿梭,只要给我定义一个靶心(标签),我就可以打破逻辑直接到达,如下面示例。

例子:01.if(网卡未初始化){
02. // 初始化网卡
03.if(初始化出错)
04. goto error;
05.}
06.
07.char * buf = (char*)malloc(20);
08.if(接受网卡数据){
09. if(数据较验错误)
10. goto checkNumError;
11. //写入到buf中
12.}else{
13. goto timeupError;
14.}
15.
16.checkNumError:
17. // 处理较验出错
18. goto freeMem;
19.timeupError:
20. // 处理超时出错
21.freeMem:
22. free(buf);
23.error:
24. // 其它善后处理

通过上面的代码可以看出,使用goto关键字,程序逻辑非常的自由,网卡初始化出错时,直接跳到23行执行,第9行,数据较验出错,
直接跳到16行,然后处理完后跳到21行,执行buf的内存释放。虽然可以看到代码逻辑很自由,但是还是会发现有点混乱,如果程序员没有
足够的代码经验,很容易出现逻辑问题,因此很多派系的编码规范中规定,禁止或尽量不使用goto关键字,很容易让程序员范迷糊。但是
在很多场合下,使用goto关键字可以更方便快捷,比如:错误处理时,其实上面的例子就是一个简单的驱动错误处理例子。

注意:1)标签后面的代码会被依次执行,如上述代码18行,如果不使用goto,那么就会去执行19行后面的错误处理代码了。
2)在含有大量goto语句时,应该按照“先跳后出”的准则去设计逻辑,因为通常在标签处要做一些前面逻辑处理,越在前面声明的变量
或内存空间,越应该在最后去释放,如前面的例子。其大概逻辑如下比如:
01.goto error:
02.……
03.goto checkNumError:
04.……
05.goto timeupError:
06.……
07.
08.timeupError:
09.……
10.checkNumError:
11.……
12.error:
13.……

5. static 静态变量

在全局数据区分配内存;未经初始化的静态全局变量会被程序自动初始化为0(自动变量的值是随机的,除非它被显式初始化)作用域仅限于
变量被定义的文件中。

全局变量和全局静态变量的区别:

   (1)全局变量是不显式用static修饰的全局变量,但全局变量 默认是静态的,作用域是整个工程,在一个文件内定义的全局变量,在另一个
文件中, 通过extern 全局变量名的声明,就可以使用全局变量。

   (2)全局静态变量是显式用static修饰的全局变量,作用域是所在的文件,其他的文件即使用extern声明也不能使用。

静态函数:

在函数的返回类型前加上static关键字,函数即被定义为静态函数。静态函数与普通函数不同,它只能在声明它的文件当中可见,不能被其
它文件使用。其它文件中可以定义相同名字的函数,不会发生冲突。

6. const 在程序执行过程中不可更改的常量值

  (1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;
  (2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;
  (3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
  (4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;
  (5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。例如:
const classA operator*(const classA& a1,const classA& a2);

例如:#define PI 3.14159 //常量宏

const double Pi = 3.14159 //此时并未将Pi放入ROM中

...

double i = Pi; //此时为Pi分配内存,以后不再分配!

double I = PI; //编译期间进行宏替换,分配内存

double j = Pi; //没有内存分配

double J = PI; //宏替换,又一次分配内存

const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是像#define一样给出的是立即数,所以,const定义的常量在程序运行过
程中只有一份拷贝,而#define定义的常量是在内存中有若干个拷贝。

提高效率

编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这也使得它成为一个编译期间的常量,没有了存储与读内存的操作,
使得它的效率提高。

7. sizeof 计算表达式或数据类型的字节数

例如:sizeof(char) = 1

int a[20];
sizeof(a) = 20

8. typedef 重新进行数据类型定义

1)typedef的最简单实用
定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。比如:

typedef unsigned long OT_U32;
typedef unsigned short OT_U16;
typedef unsigned char OT_U8;

2)typedef与结构结合使用

typedef struct tagMyStruct
{
  int iNum;
  long lLength;
} MyStruct;

   这语句实际上完成两个操作:

   a. 定义一个新的结构类型

struct tagMyStruct
{
  int iNum;
  long lLength;
};

   分析:tagMyStruct称为“tag”,即“标签”,实际上是一个临时名字,struct 关键字和tagMyStruct一起,构成
了这个结构类型,不论是否有typedef,这个结构都存在。

   b. typedef为这个新的结构起了一个名字,叫MyStruct typedef struct tagMyStruct MyStruct;

---------------
将一个结构体定义为全局变量;
typedef struct
{
unsigned char Unit; //单位 --
unsigned int Weight; //重量数据 --
unsigned char Dp; // .
unsigned char H1; // bluetooth icon
unsigned char H2; // :
unsigned char H3; // bluetooth icon
}LED_Display;

c文件中定义:LED_Display Hs4Led;
H文件中定义:extern LED_Display Hs4Led;

8. union 联合类型数据

在一个结构(变量)里,结构的各个成员顺序排列存储,每个成员都有自己的存储位置,联合变量的所有成员共享一片
存储区,因此,一个联合变量在每个时刻只能保存它的一个成员的值。
typedef union
{
unsigned long int dword;
unsigned int word[2];
unsigned char byte[4];
}Bytes4;

分析:
第一步:定义一个共同体
union
{
unsigned long int dword;
unsigned int word[2];
unsigned char byte[4];
}Bytes4;
第二步:为此共同体起个名字

typedef union Bytes4;

第三步:使用时,直接用Bytes4即可

9. asm 汇编类型

#define NOP() asm("nop")

10.enum 枚举

一般的定义方式如下:
enum enum_type_name
{
ENUM_CONST_1,
ENUM_CONST_2,
...
ENUM_CONST_n
} enum_variable_name;

注意:enum_type_name 是自定义的一种数据数据类型名,而enum_variable_name 为enum_type_name类型的一个变量,也就是我们
平时常说的枚举变量。实际上enum_type_name类型是对一个变量取值范围的限定,而花括号内是它的取值范围,即enum_type_name
类型的变量enum_variable_name 只能取值为花括号内的任何一个值,如果赋给该类型变量的值不在列表中,则会报错或者警告。
ENUM_CONST_1、ENUM_CONST_2、...、ENUM_CONST_n,这些成员都是常量,也就是我们平时所说的枚举常量(常量一般用大写)。

enum 变量类型还可以给其中的常量符号赋值,如果不赋值则会从被赋初值的那个常量开始依次加1,如果都没有赋值,它们的值从0
开始依次递增1。如分别用一个常数表示不同颜色:
enum Color
{
GREEN = 1,
RED,
BLUE,
GREEN_RED = 10,
GREEN_BLUE
}ColorVal;

其中各常量名代表的数值分别为:
GREEN = 1
RED = 2
BLUE = 3
GREEN_RED = 10
GREEN_BLUE = 11

二、枚举与#define 宏的区别

下面再看看枚举与#define 宏的区别:
1)#define 宏常量是在预编译阶段进行简单替换。枚举常量则是在编译的时候确定其值。
2)一般在编译器里,可以调试枚举常量,但是不能调试宏常量。
3)枚举可以一次定义大量相关的常量,而#define 宏一次只能定义一个。

10. if# else#
if(条件表达式)
语句1;
else
语句2;

if()
语句1;
else if()
语句2;
else if()
……………………
else 语句n

说明:else总是与最近的if相配对

11. switch/case语句

switch(表达式)
{
case 常量表达式1: {语句1;} break;

case 常量表达式2: {语句2;} break;

case 常量表达式3: {语句3;} break;

…………………………………………

case 常量表达式n: {语句n;} break;

default: {语句d;} break;
}

说明:a.case常量表达式可以是整形或字符型,也可以是枚举型数据
b.case和default的先后顺序不影响执行结果
c.没有break则控制执行下一个case语句,有break则跳出switch语句

12. while语句

while(条件表达式)
{
语句;
}

说明:当条件表达式为真时,则重复执行括号里面的语句,一直执行到表达式的结果为假时为止
如果条件表达式从一开始为假,则后面的语句一次也不会被执行

先判断,后执行
do
{
语句;
}
while(表达式);

说明:先执行一次,然后再判断
任何条件下,循环体语句至少会被执行一次

13. for语句

for(初值表达式1;循环条件表达式;更新表达式)
{
语句;
}

说明:先求表达式初值,判断是否成立,成立则执行语句,然后更新表达式,再判断;
不成立则推出for循环;

11. break 和 continue

break只能跳出它所处的那一层循环,结束整个循环;
continue则只结束本次循环下面的语句,而不终止整个循环的执行;

C语言之关键字

时间: 2024-10-06 21:56:45

C语言之关键字的相关文章

c语言const关键字

作者:沉默羔羊 c语言const关键字: --  特点. 使用该关键修饰的变量不能被改变.      --指针常量. demo:   const char *p或者是 char const * p --常量指针. demo: char * const p      --常量指针和指针常量. 1.常量指针指的是如 char * const p, p是一个常量,p不能改变指向. 2.指针常量指的是如char const *p,   p指向一个字符常量,p可以改变指向.但是不能改变*p. --对于常量

C语言中关键字volatile的含义【转】

本文转载自:http://m.jb51.net/article/37489.htm 本篇文章是对C语言中关键字volatile的含义进行了详细的分析介绍,需要的朋友参考下 volatile 的意思是“易失的,易改变的”.这个限定词的含义是向编译器指明变量的内容可能会由于其他程序的修改而变化.通常在程序中申明了一个变量时,编译器会尽量把它存放在通用寄存器中,例如ebx.当CPU把其值放到ebx中后就不会再关心对应内存中的值.若此时其他程序(例如内核程序或一个中断)修改了内存中它的值,ebx中的值并

<<黑马程序员>> C语言的关键字、标示符和注释

C语言的关键字 c语言总共提供了32个关键字: 特点: ①  C语言的关键字全部为小写字母. ②  关键字在开发工具或者智能文本编辑工具中会显示特殊颜色的字体,默认情况下,C语言                 的关键字在Xcode中都会显示紫褐色. C语言的关键字最主要的有 : int . return.  C语言的标示符 1 什么是标示符 C语言的标示符就是在程序中自定义的一些符号和名称,要跟我们的关键字区分开,关键字是C语言提供的符号,标示符是程序员自己定义的. 2 标示符的命名规则(必须

C 语言 const 关键字

#include <stdio.h> int main(void){ int i = 1; int j = 100; const int * temp = &i; printf("%d\n",*temp); i = 2; printf("%d\n",*temp); temp = &j; printf("%d\n",*temp); return 0; } 输出 12100 #include <stdio.h>

黑 马 程 序 员_视频学习总结&lt;c语言&gt;----01 关键字、标识符、注释、 常量、变量

---------------------- ASP.Net+Unity开发..Net培训.期待与您交流! ---------------------- 一.关键字 1.关键字就是C语言提供的有特殊含义的符号,有些地方也叫做“保留字”. 2.C语言一共提供了32个关键字,这些关键字都被C语言赋予了特殊含义. auto double int struct break else long switch case enum register typedef char extern return uni

C语言的关键字与注释

C语言的关键字包括:(32个) auto double int struct break else long switch case enum register typedef char extern return union const float short unsigned continue for signed void default goto sizeof volatile do if while static 关键字的特征 1>  全部都是小写 2>  在开发工具或者智能文本编辑

C语言void关键字的深刻含义

C语言void关键字的深刻含义 1.概述 本文将对void关键字的深刻含义进行解说,并详述void及void指针类型的使用方法与技巧. 2.void的含义 void的字面意思是“无类型”,void *则为“无类型指针”,void *可以指向任何类型的数据. void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变量,让我们试着来定义: void a; 这行语句编译时会出错,提示“illegal use of type 'void'”.不过,即使void a的编译不会出错,它也

C语言中关键字auto、static、register、const、volatile、extern的作用

原文:C语言中关键字auto.static.register.const.volatile.extern的作用 关键字auto.static.register.const.volatile.extern 这些关键词都是c++基础知识,我整理了一下,希望对新学的朋友们有用: (1)auto 这个这个关键字用于声明变量的生存期为自动,即将不在任何类.结构.枚举.联合和函数中定义的变量视为全局变量,而在函数中定义的变量视为局部变量.这个关键字不怎么多写,因为所有的变量默认就是auto的. (2)reg

C语言register关键字—最快的关键字 ---------------转自http://blog.sina.com.cn/s/blog_6a1837e90101128k.html

register:这个关键字请求编译器尽可能的将变量存在CPU内部寄存器中,而不是通过内存寻址访问,以提高效率.注意是尽可能,不是绝对.你想想,一个CPU 的寄存器也就那么几个或几十个,你要是定义了很多很多register 变量,它累死也可能不能全部把这些变量放入寄存器吧,轮也可能轮不到你. 一.皇帝身边的小太监----寄存器 不知道什么是寄存器?那见过太监没有?没有?其实我也没有.没见过不要紧,见过就麻烦大了.^_^,大家都看过古装戏,那些皇帝们要阅读奏章的时候,大臣总是先将奏章交给皇帝旁边的