在程序中如果出现了字符串形式,编译器在处理的时候通常会在其末尾添加一个‘\0'符号,作为字符串的结束标识。
通常,字符串常量在程序中有两种可能的身份——1、字符数组的初始化列表;2、真正的字符串常量。
1、字符数组的初始化列表
例如,有
<span style="white-space:pre"> </span>char string[] = "hello";
</pre><p><span style="white-space:pre"> </span>在这里出现了字符串“hello”,编译器在处理的时候会为其添加一个’\0‘。这里是将字符串赋给数组,因为生命数组时编译器会分配内存,因此字符串会被存放在分配的内存中,即该句代码等价于</p><p></p><pre name="code" class="html"><span style="white-space:pre"> </span>char string[] = {'h','e','l','l','o','\0'};
</pre><span style="white-space:pre"> </span>这里的字符串的“容身之所”会根据数组的作用域而言,如果是静态数组则存放在静态数据区,如果数组是在某个函数中声明的,则字符串将被存放在栈中。赋值之后我们就无需再考虑字符串了,因为它已经被存放在数组中了,接下来的工作就是对数组进行所需要的操作了。<p></p><p></p><p><span style="white-space:pre"> </span><strong>2、作为字符串常量</strong></p><p><span style="font-weight: bold; white-space: pre;"> </span>当作为字符串常量在程序中被使用时常常会生成一个指向字符的常量指针。此时该字符串是一个常量,将被编译器放置在常量区中,然后得到该字符串首个字符在此常量区中的地址,这个地址就是该字符串常量的直接值,字符串常量的直接值并不是该字符串自己本身。即“hello”的值是’h‘在常量区中的地址。因此可以有</p><p><pre name="code" class="cpp"><span style="white-space:pre"> </span>char *pt = "hello";
由于字符串是存放在常量区中,因此,只能通过指针对其进行读,而不能修改其中的值。例如可以有
<span style="white-space:pre"> </span>char ch = pt[0];
如下的操作将出现异常,即无法修改常量区中的值,
<span style="white-space:pre"> </span>pt[0] = 'p';
让人纠结的是上面的代码可以通过编译,但是会在程序运行的时候发生异常,这样会让编程人员在编写程序的时候不容易发现这种错误,因此在C++中有所改进,即将字符串常量赋给一个常量指针,即
<span style="white-space:pre"> </span>char const *pt = "hello";
这样可以在试图访问pt[0]的时候,在编译阶段就可以发现错误。所以此处的字符串常量可以理解为常量字符数组。
3、输出字符指针
如果是以字符串格式(%s)输出字符指针,输出的机制是从当前指针所指向的空间开始,一直往后输出相邻的空间数据,直到遇到一个’\0‘字符为止。
因此下面的语句将都输出hello
<span style="white-space:pre"> </span>printf("%s\n",pt);
<span style="white-space:pre"> </span>printf("%s\n",string);
这里都能顺利输出,因为字符指针pt和string都是一字符串初始化的,因此在结尾都会有一个’\0‘字符。