一、void 关键字
void * 表示“空类型指针”,可以指向任何类型的数据。
void a 在VC++6.0编译器上编译会报错,但是,就算是不报错,这个代码也没有一点实际意义。
那么void 真正发挥作用在于:
(1)对函数返回的限定;
(2)对函数参数的限定。
float *p1;
int *p2;
p1 = p2; //错误,要变成 p1 = ( float *) p2;
void *p1;
int *p2;
p1 = p2; //正确,空类型包含有类型;
p2 = p1; //错误,上面的正确,并不代表void * 也可以无需强制类型转换地赋给其它类型的指针。
1、void 修饰函数返回值和参数
(1)如果函数没有返回值,那么应声明为 void 类型,否则会在C中默认为 int 型
(2)如果函数无参数,那么应声明其参数为 void
因为在Turbo C2.0中,可以给没有参数的函数传递任意类型的参数,但是,在VC++6.0中编译不通过。为了避免这种,若函数没有参数,指明参数为void
2、void 指针
(1)void * pvoid;
pvoid ++; //错误
pvoid += 1; //错误,这是在ANSI标准下面。所以要小心使用void 指针类型。
(2)如果函数参数可以是任意类型的,那么将其声明为void *
(3)void 不能代表一个真实的变量
因为定义变量的时候一定要分配内存,定义void 类型变量,编译器到底分配多大的内存呢,void 的存在体现了一种抽象。
二、return 关键字
功能:用来终止一个函数并返回其后面跟着的值。
注意:return 语句不可返回指向“栈内存”的“指针”,因为该内存在函数体结束时被自动销毁。
三、const关键字
const int Max = 100;
int Array[Max];
在.c文件中,这样编译不可以通过;而在.cpp中,这样完全正确,因为C++扩展了const 定义。那么可以看到在C中,虽然用const进行了修饰,但其仍然是变量。
1、节省空间,避免不必要的内存分配,同时提高效率
编译器通常不为普通const 只读变量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,这使得它的效率也很高。
如:
#define M 3 //宏常量
const int N = 5; //此时并没有将N放入内存中
.............
int i = N; //此时为N分配内存,以后不再分配
int j = M; //预编译期间进行宏替换,分配空间
int k = N ; //没有分配内存
int p = M; //再进行宏替换,又分配一次内存。
总结的const 和 #define 的区别:
(1)const 定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define 一样给出的是立即数
所以,const 定义的只读变量在程序运行过程中只有一份拷贝(因为它是全局的只读变量,存放在内存的静态区)
而#define 定义的宏常量在内存中有若干个拷贝。
(2)#define 宏是在预编译阶段进行替换,而const 修饰的只读变量是在编译的时候确定其值。
(3)#define 宏没有类型,而const 修饰的只读变量具有特定的类型。
2、修饰一般变量
可以有两种表示类型: int const i = 2; 或 const int i = 2;
3、修饰数组
int const a[5] = {1,2,3,4,5} 或 const int a[5] = {1,2,3,4,5}
4、修饰指针
const int *p; //p可变,p指向的对象不可变。
int const *p; //p可变,p指向的对象不可变。
int *const p; //p不可变,p指向的对象可变
const int *const p; //p和p指向的对象都不可变
理解和记忆的方法:去掉类型说明符,看const和*p 还是和p 距离较近,即是修饰哪个。
5、修饰函数参数
用法:当不希望这个参数值被函数体内意外改变时使用。如 void fun( const int i),即 i 在函数体中不能改变。
6、修饰函数的返回值
用法:返回值不可被改变
通过上面的一些总结,或许我们可以将 const 看是 readonly