先来看一段代码,我的好多朋友都猜错了它的运行结果:
#include <iostream> using namespace std; int main(int argc, char const *argv[]) { char *p="Seven"; p[0]='L'; cout<< p; return 0; }
来仔细看看
char *p="Seven";
这句话呢,首先是声明和定义了一个指针,一个指向char的指针。
然后,后面的是对这个指针进行初始化。
但是,请注意,右边并不是一个指针,而是一个其他东西。
它是什么,我们一会再说。
当你要初始化一个typeA的变量,赋值号的右边却是一个typeB的东西。
编译器可能会做一些小动作,有一种动作叫做implicit conversion.
举个例子好了:
int x=1.2;
我们声明和定义了一个int类型的x。
然后接下来,我们对int进行初始化,但是右边给的是个小数1.2。
那么最后x实际上被赋值为的是1.
实际上,编译器,读到了1.2这个literal之后,把它换成了1.
然后,真实的情况是把1赋给了x;
现在我们回到上面的故事。
来看看给p初始化的时候,右边用的那个"Seven"到底是什么?
这个东西在c++里面,叫做string literal。
它的type是 const char[]
那么,右边是一个元素为常量的数组。
左边是一个指针,我们要赋值之前,要先把右边转换成一个指针。
没错,这个指针指向的是 上面这个元素为常量的数组的第一个元素。
接下来的故事,你大概能够看到了,你要尝试做的是改变常量的值。
这个在c++里面是undefined behaviour.
它会由编译器和操作系统共同决定。
目前,在自己的编译器MinGW,还有朋友的VC6.0,VS2010的编译器,加上windows。
我们得到的结果都是,程序崩溃了。
有可能是编译器允许了这种操作,但是,操作系统敏感地拒绝了。
实际上,把string literal赋值给一个指针,这个在现在是被不提倡的一种做法。
或者说在语言的设计者那里,他们觉得这个是deprecated feature。
但是,有太多的老的代码使用这个。
他们才保留了这个特性。