【问题标题】:Unexplainable behaviour when printing out strings in C在 C 中打印字符串时出现无法解释的行为
【发布时间】:2020-04-26 16:26:48
【问题描述】:

以下代码按预期工作并输出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;
  }

}

但如果我删除添加空字符的行

  hallo[3] = '\0';

我得到像 wBCÇL, ╗BCÄL, ┬BCNL 这样的随机输出。

为什么会这样?我期望 printString() 中的循环永远运行,因为它没有遇到“\ 0”,但是“A”、“B”和“C”发生了什么?为什么 B 和 C 仍然出现在输出中,但 A 被替换为一些随机字符?

【问题讨论】:

  • 可能是因为它碰巧碰到了 '\r' 的值,这会将光标重置到我猜测的行首。
  • 因为在第二种情况下,您有一个字节数组(不是字符串),在您希望的地方没有空字节。使用char hello[100] = ""; 或等效项将所有内容初始化为空字节。
  • @Jonathan Leffler 这并不能解释我眼中的这种行为。是的,空字节(故意)丢失。然后循环不应该结束,直到它偶然在内存中的某个地方找到一些空字节。我明白了。但是为什么最初的'A'被随机字符代替?这与缺少空字符有什么关系?
  • 未定义的行为可以为所欲为,而且没有任何意义。正如其他人所建议的那样,其中一个字符可能是回车符。
  • 事实上:如果我在不同的机器上运行相同的代码,我会得到“ABC”后跟随机字符。从中学到了很多,谢谢!

标签: c printf null-terminated null-character


【解决方案1】:

您声明的 hello 未初始化并填充随机字节

int main()
{
 char hello [100];
 ...
}

如果你想要零初始化数组使用

int main()
{
 char hello [100] = {0};
 ...
}

【讨论】:

  • 如前所述,我是故意这样做的。我不明白的是为什么它从来没有打印过'ABC',然后是一些随机字符,这是我所期望的。上面已经回答了问题,现在一切都说得通了。
【解决方案2】:

在我的数组 hello 之后的内存单元中的某个地方肯定有 \r 的值。这就是我的角色“A”被覆盖的原因。

在其他机器上,“ABC”按预期输出,后跟随机字符。

用0初始化数组,这里特意省略,当然可以解决问题。

编辑: 我让代码以二进制形式打印出每个字符,而 toPrint[5] 确实是 00001101,它是 \r 的 ASCII 码(回车)。

【讨论】:

  • 我认为您已经非常正确地回答了您的问题,至少比其他人更好。但是,如果 hello 之后找到限制 '\0',则您正在调用未定义的行为。请标记此答案。
  • 下次运行时,\r 可能不在您找到的位置。
【解决方案3】:

当您声明automatic 之类的char hello [100]; 时,首先要了解的是100 字节几乎可以包含任何内容。你必须明确地为每个字节赋值才能做/有一些有意义的事情。

当您找到 \0 又名 NUL 字符时,您将终止循环。现在,如果您注释掉将\0 放在字符c 之后的指令,您的循环将一直运行,直到您真正找到\0

您的数组有时可能包含\0,也可能不包含。您可能会超出100 字节仍在寻找\0 并调用undefined behaviour。当您尝试使用一块未分配的内存时,您也会调用 UB。

【讨论】:

    猜你喜欢
    • 2020-10-29
    • 1970-01-01
    • 2018-11-26
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多