在《C语言深度解剖》这本书里,看到下列这段:
这里谈到了字符数组里的单个元素值为0就相当于,字符数组代表的字符串结束了。但平时听到的都是说‘\0’代表字符串结束。所以引发了‘\0’和0之间的关系和区别。
先看下列代码,因为strlen在计算长度时会忽略最后一个空字符‘\0’,为了把它打印出来,加了1.
#include <stdio.h>
#include <string.h>
int main()
{
char str1[] = { "cxjr.21ic.org" };
printf("str1: %s\n", str1);
printf("str1 length: %d\n", strlen(str1));
for (int i = 0; i < strlen(str1) +1 ; i++) {
printf("str1[%d]: %c\n", i, str1[i]);
}
return 0;
}
运行结果为:
可以看到最后一个字符是空的,假如用%d来打印的话,是这样的:
也就是说,字符数组如果单个打印出来(用%d),编译器自动添加的最后一个表示结束的‘\0’打印出来确实是0,所以当对字符数组的单个元素赋值为0时,确实对应'\0' 这个字符,也就是说用strlen来操作的话,编译器就以为在这里结束了,后面的都不算了。
其实‘\0’是在告诉编译器,这是一个空字符,对应ASCII码表里的第一个字符,当用%d打印时,他的值就是0,当用%c打印时,是空,没有任何显示。
调试过程中发现一些问题,比如把上述的字符数组变一下:
char str1[4] = { 'a','b','0', 'c'};
printf("str1: %s\n", str1);
printf("str1 length: %d\n", strlen(str1));
for (int i = 0; i < strlen(str1) + 1 ; i++) {
printf("str1[%d]: %c\n", i, str1[i]);
}
return 0;
输出结果如下,首先0输出了,这个‘0’和 ‘\0’ 有本质的区别,前者是字符0,后者是空字符,前者对应的ASCII码为48,后者为0。并且输出结果出现乱码:
原因出在str1长度只有4,赋值完后,没有空间留给表示结束的‘\0’空字符。所以strlen函数算长度的时候,没有在4之后就立即结束,而应该是直到遇到后面有‘\0’的时候才结束,不过"为什么是90,而 i 却总共循环到33为止" 就不知道了。总之对字符数组赋值要注意!
如果把str1长度改成5:
char str1[5] = { 'a','b','0', 'c'};
printf("str1: %s\n", str1);
printf("str1 length: %d\n", strlen(str1));
for (int i = 0; i < strlen(str1) + 1 ; i++) {
printf("str1[%d]: %c\n", i, str1[i]);
}
return 0;
运行就是正常的,看来是自动在最后一个位置补上了‘\0’。strlen算出的长度也还是4。
用%d打印,是0没错:
char str1[] = { 'a','b','0', 'c', '\0'};
//字符串赋值,系统自动添加
char str1[] = {"ab0c"}
//人工添加
char str2[] = {'a','b','0','c','\0'};
char str3[] = {"ab0c\0"};
//留一个空位置给'\0'
char str4[5] = {'a','b','0','c'};
char str5[5] = {"ab0c"};//但通常这样写的时候我们就不指定长度了
请注意字符数组赋值的操作,参考下文,写得不错:
(60条消息) C语言中的‘\0’是什么?_子春_贰叁的博客-优快云博客
另外要注意,如果用单个字符赋值的方法,把‘0’改成0 :
char str1[] = { 'a','b', 0, 'c', '\0'};
printf("str1: %s\n", str1);
printf("str1 length: %d\n", strlen(str1));
for (int i = 0; i < strlen(str1) + 1 ; i++) {
printf("str1[%d]: %c\n", i, str1[i]);
}
return 0;
这样输出的结果如下:
字符数组长度为2,也就是说,第三个0,其实充当了‘\0’的作用,就是字符数组的结束符号了,str1[3] = 0 等价于 str1[3] = '\0'。这点也请注意,字符一定要用单引号,不然一不小心就出错了。