字符串结束标志(划重点)
字符串是一系列连续的字符的组合,要想在内存中定位一个字符串,除了要知道它的开头,还要知道它的结尾。找到字符串的开头很容易,知道它的名字(字符数组名或者字符串名)就可以;然而,如何找到字符串的结尾呢?C语言的解决方案有点奇妙,或者说有点奇葩。
在C语言中,字符串总是以'\0'
作为结尾,所以'\0'
也被称为字符串结束标志,或者字符串结束符。
'\0'
是 ASCII 码表中的第 0 个字符,英文称为 NUL,中文称为“空字符”。该字符既不能显示,也没有控制功能,输出该字符不会有任何效果,它在C语言中唯一的作用就是作为字符串结束标志。
C语言在处理字符串时,会从前往后逐个扫描字符,一旦遇到'\0'
就认为到达了字符串的末尾,就结束处理。'\0'
至关重要,没有'\0'
就意味着永远也到达不了字符串的结尾。
由" "
包围的字符串会自动在末尾添加'\0'
。例如,"abc123"
从表面看起来只包含了 6 个字符,其实不然,C语言会在最后隐式地添加一个'\0'
,这个过程是在后台默默地进行的,所以我们感受不到。
下图演示了"C program"
在内存中的存储情形:
需要注意的是,逐个字符地给数组赋值并不会自动添加'\0'
,例如:
- char str[] = {'a', 'b', 'c'};
数组 str 的长度为 3,而不是 4,因为最后没有'\0'
。
当用字符数组存储字符串时,要特别注意'\0'
,要为'\0'
留个位置;这意味着,字符数组的长度至少要比字符串的长度大 1。请看下面的例子:
- char str[7] = "abc123";
"abc123"
看起来只包含了 6 个字符,我们却将 str 的长度定义为 7,就是为了能够容纳最后的'\0'
。如果将 str 的长度定义为 6,它就无法容纳'\0'
了。
当字符串长度大于数组长度时,有些较老或者不严格的编译器并不会报错,甚至连警告都没有,这就为以后的错误埋下了伏笔,读者自己要多多注意。
有些时候,程序的逻辑要求我们必须逐个字符地为数组赋值,这个时候就很容易遗忘字符串结束标志'\0'
。下面的代码中,我们将 26 个大写英文字符存入字符数组,并以字符串的形式输出:
1. #include <stdio.h>
2. int main(){
3. char str[30];
4. char c;
5. int i;
6. for(c=65,i=0; c<=90; c++,i++){
7. str[i] = c;
8. }
9. printf("%s\n", str);
10.
11. return 0;
12. }
在 VS2015 下的运行结果:
ABCDEFGHIJKLMNOPQRSTUVWXYZ口口口口i口口0 ?
口
表示无法显示的特殊字符。