由字符串常量引发的思考
晚上帮WL做些阿里的面试题,遇到一个关于字符串常量和字符串变量的问题,感觉有些不确定,就回来研究一下。
首先看个例子吧:char *p="hello";p[2]='j'; 这里有问题吗?既然这样问了,肯定有噻。
这里普及下我之前没注意的事实:char *p="hello"得到的是字符串常量;char p[]="hello"得到的是字符串变量。事实上,字符串常量都放在一个称之为文字常量区的神奇地方。
我们看个代码吧:
#include <iostream> using namespace std; int j=3; char *a="lihuan"; char *b="lihuan"; char e[]="lihuan"; char f[]="lihuan"; int main(){ cout<<(void*)a<<endl<<(void*)b<<endl; cout<<&j<<endl<<&a<<endl<<&b<<endl; cout<<(void*)e<<endl<<(void*)f<<endl; return 0; }
猜猜结果是什么?
我们可以发现,a和b指向同一个地方,而e和f指向的地方不一样,且和a、b的地方也不一样。而j、e、f的地址是挨着的。其实,a和b指向的就是文字常量区,而j、e、f都在静态存储区(因为他们都是全局变量)。
这里普及一个知识:
一个程序的运行起来后,其在内存中有5个区域
1. 程序代码区
这个很简单,代码要执行,肯定要加载进内存, 我们不必关心。
2. 文字常量区
一般我们这样定义一个字符串时,其是在文字常量区的:
char* s1 = "hello, world";
char* s2 = "hello, world";
这里, s1和s2指向的是同一个字符串
文字常量区存储的都是常量,常量一经初始化,就不允许被修改
3. 静态存储区
全局变量,静态变量会放在这个区域,事实上,全局变量也是静态的。
4. 栈
局部变量就是在栈里的。另外,函数调用时的参数也是在栈里的,这个现在不必关心
5. 堆
malloc或new出来的内存就是在堆里的,需要程序员自己管理清除。
顺便聊一下指针常量与常量指针的区别吧:
1.常量指针:
在C/C++中,常量指针是这样声明的:
1)const int *p;
2)int const *p;
常量指针的使用要注意,指针指向的对象不能通过这个指针来修改,可是仍然可以通过原来的声明修改,也就是说常量指针可以被赋值为变量的地址,之所以叫做常量指针,是限制了通过这个指针修改变量的值。例如:
int a = 5;
const int *c = &a; // 这是合法的,非法的是对c的使用
*c = 6; // 非法,但可以这样修改c指向的对象的值:a = 6;
2.指针常量:
在C/C++中,指针常量这样声明:
int a;
int *const b = &a; //const放在指针声明操作符的右侧
因为指针常量是一个常量,在声明的时候一定要给它赋初始值。一旦赋值,以后这个常量再也不能指向别的地址。
虽然指针常量的值不能变,可是它指向的对象是可变的,因为我们并没有限制它指向的对象是常量。
char *a = "abcde1234";
char *const c = &a;
下面的操作是可以的。
a[0] = 'x'; // 我们并没有限制a为常量指针(指向常量的指针)
3.指向常量的指针常量:
在C/C++中,这么声明:
const int a = 25;
const int * const b = &a;
看,指针声明操作符左边有一个const,说明声明的是一个指向常量的指针。再看,指针声明操作符右边有一个const,说明声明的是一个指针常量。前后都锁死了,那么指向的对象不能变,指针常量本身也不能变。
可以参考下:http://www.cnblogs.com/witty/archive/2012/04/06/2435311.html