先测试C语言的const:
#include<stdio.h> int main() { const int a = 10; //等价于 //int const a = 10; //a = 11;//err int s = 1; const int *p=&s; //*p = 10;//err 改变p所指向的内容 p = NULL;//改变p是可以的 int *const p1 = &s; //p1 = NULL;err *p1 = 100; return 0; }
不是指针变量的表达式,const放在类型的前后都没关系,但是在指针变量中,const的位置就有讲究了,此时要分清楚是指针变量的值是只读的还是指针所指向的内存空间是只读的。而且,C语言中,const是个假const:
#include<stdio.h> int main() { const int a = 10; //等价于 //int const a = 10; //a = 11;//err //看似不能改变a的值,其实只是不能直接更改而已,但可以间接修改 int *p = &a;//C语言中这种类型不符合是可以被接受的,c++中不行 *p = 100; printf("%d\n", a); return 0; }
运行结果显示a的值被改变。所以,在C语言中,const不是真正的常量,只是不能直接修改而已,因此,在那些必须要常量的场合,不能用const定义的变量。比如数组的维数,虽然在C99中支持了变长数组,但是很多时候我们使用的都不是VLA,因为VLA局限性比较大,不能初始化,还必须是局部变量。那么,C语言中的常量只有define和直接数字值还有就是枚举。
#include<stdio.h> enum test { saturday, sunday = 0, monday, tuesday, wednesday, thursday, friday } ; int main() { int a[friday] = { 0 }; return 0; }
枚举类型可以编译通过,因为它是真正的常量。这是在没有支持C99的前提下测试的。define自然支持就不再测试了。
那么,其实在很多时候,C语言中的代码加上了const修饰,也还是不安全的。
int main() { int a = 10; int const *p2 = &a; int * p1 = p2; *p1 = 100; printf("%d\n", a); return 0; }
上述代码还是会改变a的值,但这个例子一般我们不会这样写,不过从上面的代码中,我们可能会像下面这样写程序,因为很多时候,我们想用const指针修饰的形参。目的是不想实参被改变,但是如果不注意,还是达不到想要的效果:
#include<stdio.h> void test(int const *p) { int *p1 = p; *p1 = 100; } int main() { int a = 10; test(&a); printf("%d\n", a); return 0; }
我们把形参的指针所指向的内存空间设置成const的,就是不想实参被改变,但是还是可能会被间接修改,所以,在编写代码的时候,我们不要使用上述代码的
int *p1 = p;
因为就算你形参用const保护了,后续忘记了用const去接这样的变量,还是无用的。这提醒我们注意,应该这样去写这句
话:
int const *p1 = p;
保证接它的变量也要是const的。
c++中,const是升级过的了:
#include<iostream> using namespace std; int main() { int const a = 10; //int *p = &a;c++中,不允许这样的转换,而C语言中是可以的,c++对类型检查更为严格 int *p = (int *)&a;
*p=100; cout << a << endl; return 0; }
此时,c++不再允许我们对此进行更改,这证明了,c++中const修饰的变量是真正的常量,是不是const修饰的就如果简单了呢?那么我们再试试换个方式:
#include<iostream> using namespace std; int main() { int b = 10; int const a = b; //int *p = &a;c++中,不允许这样的转换,而C语言中是可以的,c++对类型检查更为严格 int *p = (int *)&a; *p = 100; cout << a << endl; return 0; }
可以清楚地看到,我们改变了a的值,这也就是说,在c++中,如果用一个字面值给const修饰的变量赋值,例如int const a=10;这样的a就是常量,可以用来当做数组的维数,如果用一个变量给const修饰的变量赋值,例如int const a=b;这样的a就是只读变量,不能直接修改,但可以间接修改,和c中一样了。
另外注意,由于c++中严格检查类型匹配问题,所以我们要知道,在const修饰的指针变量中,顶层const在有赋值效果的操作中将被忽略。
原文:http://www.cnblogs.com/yangguang-it/p/6663930.html