c+;中字符数组的意外输出+; 我在C++方面很缺乏经验,我写了下面的代码来看看字符和字符串是如何工作的。 #include "stdio.h" #include <iostream> #include <string> using namespace std; int main() { char asdf[] = "hello"; char test[5] = {'h','e','l','l','o'}; cout << test; } #包括“stdio.h” #包括 #包括 使用名称空间std; int main() { char asdf[]=“你好”; 字符测试[5]={'h','e','l','l','o'}; cout

c+;中字符数组的意外输出+; 我在C++方面很缺乏经验,我写了下面的代码来看看字符和字符串是如何工作的。 #include "stdio.h" #include <iostream> #include <string> using namespace std; int main() { char asdf[] = "hello"; char test[5] = {'h','e','l','l','o'}; cout << test; } #包括“stdio.h” #包括 #包括 使用名称空间std; int main() { char asdf[]=“你好”; 字符测试[5]={'h','e','l','l','o'}; cout,c++,char,C++,Char,您必须使用ascii 0字符终止测试数组。现在发生的是,在内存中它与asdf字符串相邻,因此由于测试未终止,原因是C样式字符串需要空字符来标记字符串的结尾 由于您没有将其放入数组test中,它将一直打印字符,直到找到一个为止。在您的情况下,数组asdf恰好在内存中跟随test,但这无法保证 将代码改为: char test[] = {'h','e','l','l','o', 0}; 这是未定义的行为 原始代码> char *或 char []/Cord>字符串必须在C和C++中。也就是说,字

您必须使用ascii 0字符终止
测试
数组。现在发生的是,在内存中它与asdf字符串相邻,因此由于
测试
未终止,
原因是C样式字符串需要空字符来标记字符串的结尾

由于您没有将其放入数组
test
中,它将一直打印字符,直到找到一个为止。在您的情况下,数组
asdf
恰好在内存中跟随
test
,但这无法保证

将代码改为:

 char test[] = {'h','e','l','l','o', 0};
这是未定义的行为

原始代码> char *<代码>或<代码> char []/Cord>字符串必须在C和C++中。也就是说,字符串需要以<代码> 0 \ < /代码>字符结束。您的<代码>测试(5)< /C>不这样做,所以函数输出打印在最后的<代码> o>代码>之后继续,因为它仍然在寻找空终止。

由于字符串存储在上的方式(堆栈通常向较低的地址增长),它遇到的下一个字节是
asdf[]
,您将
“hello”
分配给这些字节。内存布局实际上是这样的,箭头指示内存地址(思考指针)增加的方向:

      ---->
  +-------------------
  |hellohello\0 ...
  +-------------------
        \_ asdf
   \_ test

现在在C++和C中,字符串代码如“代码>”“hello”/COD>隐式终止,因此编译器在字符串结尾写一个隐藏的<代码> \ 0”/代码>输出函数继续打印AsDF CHAR的内容,直到它达到隐藏的<代码> \ 0”/代码>,然后停止。 如果要删除

asdf
,可能会在第一个
hello
之后看到一些垃圾,然后是一个分段错误。但这是未定义的行为,因为您读取的是
测试
数组的界限。这也解释了为什么它在不同系统上的行为不同:例如,某些compILER可能会决定在堆栈上以不同的顺序排列变量,以便在您的friends系统上,
test
实际上位于堆栈的较低位置(请记住,堆栈的较低位置意味着地址较高):

现在,当您打印
测试的内容时,它将逐字符打印
hello
文件,然后继续读取内存,直到找到
\0
文件。
..
的内容与所使用的架构和运行时高度相关,甚至可能是月亮的相位和一天中的时间(不完全严重),以便在您的朋友计算机上打印一个“随机”字符,然后停止


您可以通过将
'\0'
0
添加到
test
数组(您需要将大小更改为6)来解决此问题。但是,使用
const char test[]=“hello”
是解决此问题的最明智的方法。

cout
正在打印从给定地址开头开始的所有字符(此处为
test
,或等效符号中的
&test[0]
)直到找到空终止符为止。由于您尚未将空终止符放入测试数组,它将继续打印,直到它在内存中意外找到一个。从这一点开始,发生的行为几乎是未定义的。

最后一个字符应为
'\0'
,以指示字符串的结尾

 char test[6] = {'h','e','l','l','o','\0'};

除非有超负荷的
运算符字符序列需要(
\0

更正:

char test[6] = {'h','e','l','l','o','\0'}; // OK
//        ^                         ^^^^

哇,快速回答。非常感谢,这似乎是问题所在!打字错误:应该是
char test[6]
。谢谢-应该是
char test[]这个答案很好,但是我不确定你用笔记来说明什么。非常感谢你的解释。虽然当我删除ASDF行时,它看起来正常地显示。这是C++的魔法来修复没有null终止符的事实吗?@ KieronDowie请检查我的编辑。我添加了一些ASCII艺术图形来显示MeMor。y的布局。如果删除
asdf
,它与第二个图形类似。
..
的内容可能很容易以NUL字符开头,从而终止输出。请尝试编写一个更好的标题,这将有助于未来的研究。当然,你会推荐什么标题?我想不出一种方法来描述问题简单地说,“像是字符数组的意外输出”,也许是一些描述你遇到的情况更清楚的东西,并且允许别人研究它。你应该从书中学习C++。这将在第一章的章节里对你解释。
char asdf[] = "hello"; // OK: String literals have '\0' appended at the end
char test[5] = {'h','e','l','l','o'}; // Oops, not null terminated. UB
char test[6] = {'h','e','l','l','o','\0'}; // OK
//        ^                         ^^^^