在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.a
NUL
字符时,您将终止循环。现在,如果注释掉将
\0
放在字符
c
之后的指令,则循环将运行,直到找到
\0


数组可能在某个点包含
\0
,也可能不包含。您可能会超出
100
字节的范围,仍在查找
\0
并调用。当您尝试使用未分配的内存块时,您也会调用UB。

可能是因为它恰好碰到了“\r”的值,这将将光标重置到我猜的行的开头。因为在第二种情况下,您有一个字节数组(不是字符串),在您希望的位置没有空字节。使用“
charhello[100]=”或等价物,将所有内容初始化为空字节。@乔纳森·莱夫勒,这在我看来并不能解释这种行为。是的,空字节(故意)丢失。然后循环不应该结束,直到它意外地在内存中的某个地方找到一些空字节。我明白了。但为什么首字母“A”会被随机字符替换?这与缺少的空字符有什么关系?未定义的行为可以做它喜欢做的任何事情,而且不必有任何意义。正如其他人所建议的,可能其中的一个字符是回车符。事实上:如果我在不同的机器上运行相同的代码,我会得到“ABC”后跟随机字符。从中学到了很多,谢谢!如前所述,我是故意这样做的。但我不明白的是,为什么它从不打印“ABC”,然后再打印一些随机字符,这正是我所期望的。上面的问题已经回答了,现在一切都有意义了。我认为你的问题回答得非常正确,至少比其他人好。但是,如果在
hello
之后找到限制
'\0'
,则您正在调用未定义的行为。请标记此答案。下次运行此操作时,
\r
可能不在您这次找到它的位置。
int main()
{
 char hello [100] = {0};
 ...
}