由于是温习笔记,写的内容比较杂,比较基础。主要是写给自己看的,方便以后查阅。
今天来讲讲c中的保留字。
保留字(reserved word)
保留字又称关键字。
指在高级语言中已经定义过的字,使用者不能再将这些字作为变量名或过程名使用。
每种程序设计语言都规定了自己的一套保留字。
例如:BASIC语言规定不能使用LIST作为变量名或过程名,因为LIST是一个BASIC语言专用于显示内存程序的命令。
C有22+10 = 32个关键字
C++ 有22+10+11+20 = 63 个关键字
JAVA 有22+ 9+ 17 = 48 个关键字
ps:以上内容来自百科。
其中,C89中,(C语言标准)中,
类型说明保留字:int,long,short,float,double,char,unsigned,signed,const,void,volatile,enum,struct,union
语句定义保留字:if,else,goto,switch,case,do,while,for,continue,break,return,default,typedef
存储类说明保留字:auto,register,extern,static
长度运算符保留字:sizeof
具体含义如下:
auto |
指定变量的存储类型,是默认值 |
break |
跳出循环或switch语句 |
case |
定义switch中的case子句 |
char |
定义字符型变量或指针 |
const |
定义常量或参数 |
continue |
在循环语句中,回到循环体的开始处重新执行循环 |
default |
定义switch中的default子句 |
do |
定义do-while语句 |
double |
定义双精度浮点数变量 |
else |
定义枚举类型 |
enum |
声明外部变量或函数 |
extern |
声明外部变量或函数 |
float |
定义浮点型变量或指针 |
for |
定义for语句 |
goto |
定义goto语句 |
if |
定义if语句或if-else语句 |
int |
定义整型变量或指针 |
long |
定义长整型变量或指针 |
register |
指定变量的存储类型是寄存器变量,Turbo c中用自动变量代替 |
return |
从函数返回 |
short |
定义短整型变量或指针 |
signed |
定义有符号的整型变量或指针 |
sizeof |
获取某种类型的变量或数据所占内存的大小,是运算符 |
static |
指定变量的存储类型是静态变量,或指定函数是静态函数 |
struct |
定义结构体类型 |
switch |
定义switch语句 |
typedef |
为数据类型定义别名 |
union |
定义无符号的整型或字符型变量或指针 |
unsigned |
定义无符号的整型变量或数据 |
void |
定义空类型变量或空类型指针,或指定函数没有返回值 |
volatile |
变量的值可能在程序的外部被改变 |
while |
定义while或do-while语句 |
下面,就几个我认为比较容易用错的保留字进行分析,主要包括
return, void, const, break, continue
至于存储类说明保留字,也是难点之一,在之前博客已经描述过了,这里就不在重复了。
以下内容参阅《c程序设计竞赛实训教程》和一些大牛博客结合自己看法写的。
1.return
return:结束一个函数并返回其后面表达式中的值。
初学的时候,有些不理解main 函数中return 0;有什么用,在写程序的时候老是忘记带上了。其实,带上return 0;是很有必要的。
main函数的返回值用于说明程序的退出状态,如果返回0,表示程序正常退出,否则表示程序异常退出。返回值传递给程序的激活者(操作系统)。
如果没有写return语句的话,c99(c语言标准)规定编译器自动在生成的目标文件中加入return 0;表示正常退出。
所以,为了代码规范,我们一般都必须带上return 0;
具体操作----- return (表达式);
其中,括号是可以省略的。 一般不省略,如果返回值为表示式的时候容易造成混淆。
return返回值的类型,一般是函数定义的类型,如果return后表示式的值类型和函数值的类型不一致,则以函数函数类型为准,即:函数类型决定返回值类型。
需要注意的一点,也是易错的一点是:return不能返回指向局部变量的类型。----因为在函数结束时局部变量被自动销毁(上篇博客提及的局部变量的生存周期),则返回的指针为指向已释放的空间,再通过此指针进行操作就会产生错误。
下面通过程序具体说明:
#include<stdio.h>int *test(){ int num=3,*ptr; //num为局部变量 ptr = # return ptr; //这里,返回了指向局部变量的指针}int main ( ){ int i=4,*p; p = test(); printf("%d,%d\n",i,*p); return 0;}
看下输出结果 4,3
程序中,函数test的返回值为指向局部变量num的指针,当主函数调用test函数的时候,返回ptr指针并且赋值给p指针变量,即num变量的地址赋给了p,但是必须明白,在test函数结束的时候,局部变量num的空间被释放了,这样用p来引用这个空间就会出错。
乍一看,和预期的一样,但是实际上,这样的程序是存在隐患的。
下面改改这个程序,就知道错在哪了。
#include<stdio.h>int *test(){ int num=3,*ptr; //num为局部变量 ptr = # return ptr; //这里,返回了指向局部变量的指针}int test2(){ int x = 9,y=7; return (x+y);}int main ( ){ int i=4,*p; p = test(); i = test2(); printf("%d,%d\n",i,*p); return 0;}
运行结果: 15,7(也可能是15,9视具体环境而定。)
在这里,多了个test2函数。发现结果并不是我们预料的15,3 。 p指向空间的数据不是之前num所赋值的3.
这正印证了我们之前说过了,这样的返回存在隐患。 在test函数调用完后,系统释放之前给num分配的空间,但是p指针仍然指向那块区域。
在调用test2的时候,系统要为x,y分配空间。这时候就会把之前释放的那块空间给x,y再次分配使用,使用在赋值语句后,该空间的值发现了改变,使得*p发生了改变。
所以,切记 return不能返回指向局部变量的类型。
2.void
void :void为空类型。 void *为空类型指针。
其中,void a;是不允许的。 每次定义一个变量,系统都会为其分配空间,而void类型无法确定,系统就不知道该为它分配多大的空间,显然是不合理的。
void *p;是允许的, 因为这是一个指针变量,系统都是默认分配四个字节的空间,至于具体指向的空间总存放的数据类型,就由用户自行操作。
并且,在操作的时候,要把该void指针强制转换为相应类型的指针后才可进行操作。
如:
void *p;int a=5,b;p = &a;b = *(int *)p;//强转为int型指针。
即:
在使用void类型指针变量时,其他类型的地址可以直接赋值给void类型的指针变量,但反过来,void类型的指针变量赋值给其他类型的指针变量或取其所指空间数据时必须进行强转。
3.const
const:constant的缩写,意为不变。 即用const修饰的变量的不允许改变的。也可称为只读变量。
例如: int const m = 10; const int m = 10; (二者可以认为等价,const定义一般的变量比较简单。例如该例中都是限定m为10)
但是要注意一点,只读变量虽然值不能改变,但它还是变量,不是常量。
如 int const M = 10; int a[M]; 这样定义数组是错误的。我们知道,定义数组时,数组元素个数必须是常量(这样系统才知道要分配多大的空间),而M的本质是变量,只是值不改变的变量而已。
所以,一般我们定义数组采用这样的操作: #define M 10 int a[M];
下面讨论下const定义指针,这就比较复杂了。
const int *p;//const修饰的是*p,表示p可变(地址可变),p所指空间的内容不可变(数据不变)int const *p;//const修饰的是*p,表示p可变(地址可变),p所指空间的内容不可变(数据不变)int* const p;//const修饰的是p,表示p不可变(地址),p所指空间内容可变(数据可变)const int* const p; //表示p和p所指的空间内容均不可变
至于地址,数据,拿const int *p;举例。 此时,p=&a;操作是允许的,(修改地址)。而*p=10;是允许的(试图改变数据造成错误)。
在判读是修饰*p还是p时,我们可以先将定义中的类型标识符去掉(int),再观察const后面修饰的内容。
4,break,continue
至于break和continue,二者关系比较密切,结合探讨。 break退出当前循环,continue退出当次循环
continue
1、结束本次循环(不执行本次循环中continue后面的语句),继续下次循环条件判断;
2、不可作用于switch语句。当在switch中使用,这个continue实际是作用于其所属的循环结构;若它不属于任何一个循环,程序将因此报错!
break
1、结束整个循环,并停止下次循环条件判断;
2、可以作用于switch语句。
具体区别如下:
break和continue的区别如下:
1. break可用于switch语句,表示跳出整个switch块,而continue则不能用于switch语句
2. 它们都可用于循环语句的循环体,所谓的区别也应该是它们对循环次数的影响不同。break用于立即退出当前循环,而continue仅跳过当次循环(本次循环体内不执行continue语句后的其它语句,但下次循环还会执行)。举例说明。
int i; int s = 0; for (int i = 1; i <= 10; i++) { if (i == 6) break; s += i; }
上面的循环会因为break语句而在i=6时提前终止,这样s的最终值就是1+2+3+4+5
如将break换成continue
int i; int s = 0; for (int i = 1; i <= 10; i++) { if (i == 6) continue; s += i; }
当i=6时就不会将i累加到s中,s的最终值是1+2+3+4+5+7+8+9+10,唯独少一个6
今天就写这么多吧。 再次给《c程序设计竞赛实训教程》打个小广告,确实是本不错的书,让我学到了很多。
水平有限,如有错误,欢迎指正。
转载自原文链接, 如需删除请联系管理员。
原文链接:c语言保留字(关键字)汇总,转载请注明来源!