在C中打印字符串时无法解释的行为
以下代码按预期工作并输出在C中打印字符串时无法解释的行为,c,printf,null-terminated,null-character,C,Printf,Null Terminated,Null Character,以下代码按预期工作并输出ABC: #include <stdio.h> void printString (char toPrint [100]); int main() { char hello [100]; hello[0] = 'A'; hello[1] = 'B'; hello[2] = 'C'; hello[3] = '\0'; printString(hello); } void printString (char toPrint [10
ABC
:
#include <stdio.h>
void printString (char toPrint [100]);
int main()
{
char hello [100];
hello[0] = 'A';
hello[1] = 'B';
hello[2] = 'C';
hello[3] = '\0';
printString(hello);
}
void printString (char toPrint [100])
{
int i = 0;
while (toPrint[i] != '\0')
{
printf("%c", toPrint[i]);
++i;
}
}
我得到了随机输出,比如wBC,╗BCÄL,┬BCNL
等
为什么会这样?我所期望的是printString()中的循环永远运行,因为它不会运行到“\0”,但“a”、“B”和“C”会发生什么?为什么B和C仍然显示在输出中,但A被一些随机字符替换?您的hello声明使其未初始化,并填充了随机字节
int main()
{
char hello [100];
...
}
如果您想要零初始化数组,请使用
int main()
{
char hello [100] = {0};
...
}
纯属偶然,在我的数组hello的存储单元后面的某个内存单元中肯定有\r的值。这就是我的角色“A”被覆盖的原因 在其他机器上,“ABC”按预期输出,后跟随机字符 用0初始化数组(此处故意省略)当然可以解决问题 编辑: 我让代码以二进制打印出每个字符,toPrint[5]实际上是00001101,它是ASCII的\r(回车符)。当您声明一个like
字符hello[100]首先要了解的是,100
字节可以包含任何内容。您必须显式地为每个字节分配值,才能执行/执行有意义的操作
当您找到\0
a.k.aNUL
字符时,您将终止循环。现在,如果注释掉将\0
放在字符c
之后的指令,则循环将运行,直到找到\0
数组可能在某个点包含\0
,也可能不包含。您可能会超出100
字节的范围,仍在查找\0
并调用。当您尝试使用未分配的内存块时,您也会调用UB。可能是因为它恰好碰到了“\r”的值,这将将光标重置到我猜的行的开头。因为在第二种情况下,您有一个字节数组(不是字符串),在您希望的位置没有空字节。使用“charhello[100]=”“代码>或等价物,将所有内容初始化为空字节。@乔纳森·莱夫勒,这在我看来并不能解释这种行为。是的,空字节(故意)丢失。然后循环不应该结束,直到它意外地在内存中的某个地方找到一些空字节。我明白了。但为什么首字母“A”会被随机字符替换?这与缺少的空字符有什么关系?未定义的行为可以做它喜欢做的任何事情,而且不必有任何意义。正如其他人所建议的,可能其中的一个字符是回车符。事实上:如果我在不同的机器上运行相同的代码,我会得到“ABC”后跟随机字符。从中学到了很多,谢谢!如前所述,我是故意这样做的。但我不明白的是,为什么它从不打印“ABC”,然后再打印一些随机字符,这正是我所期望的。上面的问题已经回答了,现在一切都有意义了。我认为你的问题回答得非常正确,至少比其他人好。但是,如果在hello
之后找到限制'\0'
,则您正在调用未定义的行为。请标记此答案。下次运行此操作时,\r
可能不在您这次找到它的位置。
int main()
{
char hello [100] = {0};
...
}