char数组在最后一次迭代时复制整个单词而不是单个字母

时间:2018-02-12 17:34:01

标签: c++

2004-01-02 00:00:00

当我单步执行调试器时,一切正常,直到i = 4,在第4次交互时它从(第3次迭代)htak到htakohtako。我不明白为什么它会在最后一次迭代中复制整个单词。当我在第四次迭代中打印出c1 [i]时,它会按照预期打印出一个o但是这个额外的htako在最后会来自哪里?

2 个答案:

答案 0 :(得分:1)

您的代码有两个问题:

  • 您正在使用基于c的字符串,而忘记将终止空字符写入c2
  • 您在c2中没有足够的空间用于该空字符。

要解决第一个问题,请在while循环后添加c2[i] = 0;

要解决第二个问题,请使用char c2[6] = "Mark"; 请注意,您需要 6 来保存来自" htako"的5个字符。 +终止null char。

更详细地说:char c1[] = "htako";实际上定义了长度为6的char数组:

{ 'h', 't', 'a', 'k', 'o', \0 }

char c2[] = "Mark";定义长度为5的较短char数组:

{ 'M', 'a', 'r', 'k', \0 }

因此,当你的c循环到c2后,你的while循环结束时,你就取代了c2:

{ 'h', 't', 'a', 'k', 'o' }

请注意,您没有终止null char。另外,cince c2被隐式声明为长度为5,你没有空间来添加它。因此,当您将修改后的c2输出到cout时,由于您使用的是char [],因此cout实际上接收char *而没有长度,并且通过C-strings约定,通过搜索终止null char来确定字符串的长度。由于你没有那个空字符,cout将超过c2的末尾搜索它并且访问有效字段之外的数据是C ++程序的未定义行为。在你的特定机器上,堆栈长大,所以c1恰好在c2之后,你看到" htakohtako"打印。但实际上你的程序也可能因SEGV而失败或做任何数量的不可思议的事情。这种类型的错误称为缓冲区溢出,是许多安全漏洞的根源。不惜一切代价避免这种情况。

但实际上,std::string在这里是更合适和安全的选择,除非你只是在讨论C字符串如何在内部工作。

答案 1 :(得分:1)

你的问题的答案与记忆的布局有关。如果您检查内存,您会看到:

c2              c1 
M, a, r, k, \0, h, t, a, k, o, \0

您的代码中存在2个问题。

  1. 你有一个缓冲区溢出c2只有5个字节(Mark + null终止符),但是你覆盖空终止符,因为c1长度为6个字节(htako + null终结符)
  2. 您不是空终止字符串
  3. 您看到字符串看起来会增长,因为您覆盖了空终止符。在其他情况下,您的程序可能会崩溃。