在最早学C语言的时候,char *与char []是最让我头疼的几个问题之一。
字符串数组和字符串指针是截然不同的两个东西,如果不去在意它们之间的不同,而混合使用,可能会带来很多麻烦。让我们从这两个东西创建的过程说起。
当我们进行字符串数组的定义时
char str[] = "abc";
其实我们做了两件事:
1. 创建了一个新的字符串。
2. 创建了一个名叫“str”的变量保存字符串的首地址。
而当我们进行字符串指针的定义时
char* str = "abc";
我们只是定义了一个指针指向字符串“abc”的首地址。
等等,难道我们不需要创建字符串"abc"吗?
在C语言中,当程序开始运行时,程序会将所有用到的literal string(不知道中文怎么说)自动加载进内存中,所以字符串指针实际指向的是在程序开始运行时就已经在内存中创建的“abc”的首地址。
我们来做一个实验
#include <stdio.h> int main(int argc, char *argv[]) { char *s1 = "abc"; char *s2 = "abc"; char ss[] = "abc"; printf("%p\n", s1); printf("%p\n", s2); printf("%p\n", ss); return 0; }
在我的PC中,该程序的运行结果是
0x80485d0
0x80485d0
0xbfc2df64
可以发现字符串指针s1,s2实际指向了同一个地址。
我们常说literal string是不能更改的。当我用char *ss = "abc"定义了一字符串指针,如果在程序中试图更新ss,程序就会出错,这是因为literal string是存放在constant内存区,是不能被更改的。如果我们创建的字符串有可能被更改,那么需要先对literal string做一份拷贝,再将指针指向这个拷贝的首地址。即使用字符串数组的定义方式:char ss[] = "abc";
一个好的编程习惯是当我们使用字符串指针的定义时使用const限定符: const char* ss = "abc"; 这样如果程序试图更改这个变量,在编译时就会给出错误。