由字符串常量引发的思考

  晚上帮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

posted @ 2015-04-03 01:07  jiu~  阅读(565)  评论(0编辑  收藏  举报