C语言字符加倍代码中j初始为0时string2无输出问题
不存在你所说的「禁止设置空字符串除首元素外的其他元素」的底层机制,该异常行为是C语言两个基础特性共同作用的结果:
- C语言字符串以
\0(ASCII值为0的空字符)作为唯一结束标志,printf输出%s格式时会从传入的首地址开始逐个打印字符,直到遇到\0才终止。 - 函数内部定义的未初始化局部数组,存储的是栈空间的随机残留数据,不会默认填充
\0。
两种初始化值的行为差异分析
j初始值为-1的场景
你的源字符串nabucco长度为7,循环共执行7次,每次循环j会自增2次,循环结束后j的最终值为-1 + 7*2 =13,即你已经为string2的下标0~13完成了赋值。此时能正常输出属于巧合:string2[14]的位置刚好是栈残留的\0,作为字符串结束符被printf识别,所以可以正常打印完整结果。如果栈残留数据不符合这个条件,你同样会遇到乱码、无输出等异常。
j初始值为0的场景
该场景下循环第一次执行时,j先自增为1再赋值,最终你完成赋值的是string2的下标1~14,下标0的位置始终未被修改,保留栈的随机残留值。如果该位置的残留值刚好是\0,printf读取第一个字符就判定字符串结束,自然就不会输出任何内容,这就是你遇到的问题。
正确修正方案
只需要补全字符串结束符的处理逻辑,即可避免这类未定义行为,参考代码如下:
#include<stdio.h> #include<string.h> int main(){ char string1[20] = "nabucco"; char string2[40]; int j = 0; int len = strlen(string1); for(int i=0; i<len; i++){ string2[j++] = string1[i]; string2[j++] = string1[i]; } // 手动添加字符串结束符 string2[j] = '\0'; printf("string1=\t%s\n", string1); printf("string2=\t%s\n", string2); return 0; }
你也可以在定义string2时直接初始化为全0:char string2[40] = {0};,这样即使忘记手动加结束符,也会因为数组默认填充\0正常输出。
内容的提问来源于stack exchange,提问作者Kahn
相关产品推荐
相关产品推荐

