为何第一种C语言字符串复制实现打印时出现未知符号?
为什么第一种字符串复制写法会出现未知符号?
这问题我之前写C的时候也踩过一模一样的坑!核心原因非常明确:第一种写法没有给复制后的字符串添加C语言字符串必需的终止符'\0'。
先搞懂C语言字符串的规则:C里的字符串本质是字符数组,但必须以'\0'(空字符)作为结束标记。printf("%s")这类函数会从指定地址开始逐个输出字符,直到遇到'\0'才会停止——如果找不到这个标记,它就会继续读取内存里的随机垃圾数据,直到碰巧遇到某个'\0',这就是你看到的“未知符号”的来源。
我们来拆解两种写法的差异:
第一种写法的问题点
const char *constStr = "Hello world"; char *str = (char*) malloc(strlen(constStr) + 1), *p = str; while (*constStr) { *p = *constStr; constStr++; p++; } printf("%s\n", str); free(str);
- 原字符串
"Hello world"的末尾自带'\0',但你的循环条件是while (*constStr)——当*constStr等于'\0'时,这个条件不成立,循环直接终止了。 - 你虽然用
malloc(strlen(constStr)+1)申请了足够容纳'\0'的空间(strlen返回的是字符串长度,不包含末尾的'\0'),但这个空间里的'\0'根本没被复制进去,p指向的位置是malloc返回的未初始化内存,内容是随机的。 - 所以
printf输出时,会把复制的"Hello world"全部输出,然后继续读后面的随机垃圾数据,直到碰到某个'\0',就出现了乱码。
第二种写法为什么正常
const char *constStr = "Hello world"; char *str = (char*) malloc(strlen(constStr) + 1); for (int i = 0; i <= strlen(constStr); i++) { str[i] = constStr[i]; } printf("%s\n", str); free(str);
- 这里的循环条件是
i <= strlen(constStr):strlen(constStr)返回11("Hello world"的字符数),当i=11时,constStr[11]刚好是原字符串末尾的'\0',这一步把'\0'也复制到了str[11]的位置。 - 这样
str就成为了一个带正确终止符的合法C字符串,printf输出到'\0'就停止,自然能正常显示"Hello world"。
第一种写法的修复方案
只需要在循环结束后,手动给str加上终止符就行:
const char *constStr = "Hello world"; char *str = (char*) malloc(strlen(constStr) + 1), *p = str; while (*constStr) { *p = *constStr; constStr++; p++; } *p = '\0'; // 加上这一行,手动添加字符串终止符 printf("%s\n", str); free(str);
内容的提问来源于stack exchange,提问作者Lion King
相关产品推荐
相关产品推荐

