2004-01-02 00:00:00
当我单步执行调试器时,一切正常,直到i = 4,在第4次交互时它从(第3次迭代)htak到htakohtako。我不明白为什么它会在最后一次迭代中复制整个单词。当我在第四次迭代中打印出c1 [i]时,它会按照预期打印出一个o但是这个额外的htako在最后会来自哪里?
答案 0 :(得分:1)
您的代码有两个问题:
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个问题。
c2
只有5个字节(Mark + null终止符),但是你覆盖空终止符,因为c1
长度为6个字节(htako + null终结符)您看到字符串看起来会增长,因为您覆盖了空终止符。在其他情况下,您的程序可能会崩溃。