1:常量指针与指针常量
常量指针与指针常量名字很接近,但是两者区别很大。
常量指针是指指向常量的指针,例如:char const *st[4]="str";或者使用下面的方法,效果是一样的:const char *st[4]="str"; 它声明了一个指针变量,这个指针指向了一个常量字符串,但是由于指向的内存空间是常量,因此该地址的内容是不能修改的,例如:*st="no"; //这是不行的,因为内存空间的内容不能修改st="ok"; //这是可以的,虽然指向的内存内容不能修改,但是指针的指向是可以修改的。
指针常量是指一个指向固定内存单元的指针,其内容可以修改,但是不能改变指向的位置,例如:char *const st[4]="str";*st="ok"; //这是可以的,因为指向位置的内容可以修改。st="no"; //这样行不通,因为指针是不能改变指向位置,即如果初始化为地址0X8000,那么它只能指向这个位置,不能改变,但是0X8000的内容是可以改变的。
char *s = "abcde";
s[0] = '1';//此句在运行时出错
如下是可以的:
char s[] = "abcde";
s[0] = '1';
因为:
字符串常量是不能改的,编译后是放到只读内存(静态存储区)中的;
char[]和char*在很多地方可以通用,但是有个微妙的关系,那就是头指针相同;
因为“通过指针修改字符串常量的行为”是未定义的,上次就有个人问"为什么上述代码在TC下不报错而在VC6.0下报错"。不过,现在大多实现把常量字符串的存储空间设置为read-only,所以运行时报错;
char *s = "abcde";相当于const char *s = "abcde";
-------------------------------------------
按照楼上各位的说法,编译器应该禁止这么声明:
char *s = "abcde";
而强制我们如下声明:
const char *s = "abcde";
为什么编译器没有这么做呢?
--------------------------------------------
没错,的确因该像楼主说的那样,编译器应该禁止这种行为,进而帮助程序员写出正确的程序。
但是,这是一个特殊情况,是一个特例!
为什么这么说呢?因为char *s = "abcde";这种模式已经被很多人所使用(也包括楼主),它被使用的如此广泛以至于标准给它一些宽容:允许这样的代码通过编译。
-------------------------------------------- 《effective c++》91页注释1:
在C++ standard中,"Hello"的型别是const char[];这个型别几乎总是被视为const char*。因此我们预期,以一个字符串子面常量(string literal,例如"hello")作为一个char*变量的初值,会违反常量性。但是此种行为在C语言中实在太过频繁,所以C++ standard对于这样的初始化动作特别给与豁免。尽管如此,你还是应该避免这么做,因为那毕竟不被大家认同。