cout 返回两次字符字符串

use*_*306 3 c++ g++

以下代码的输出是

Toto
TotoToto
Run Code Online (Sandbox Code Playgroud)

但我希望只是

Toto
Toto
Run Code Online (Sandbox Code Playgroud)

为什么第二个 cout 重复输出中的字符串?

我在 Ubuntu 上使用 g++ 7.5.0 版,我不确定这是否相关。

代码如下:

#include<iostream>

using namespace std;

int main(){

  char c1[] = "Toto";
  char c2[4] = {'T','o','t','o'};


  cout << c1 << endl;
  cout << c2 << endl;


  return 0;

}
Run Code Online (Sandbox Code Playgroud)

Ton*_*roy 5

当您输出一个字符数组时,它必须 - 按照约定 - 以 null 结尾,否则您有未定义的行为

更改c2如下,它将按预期开始工作:

char c2[5] = {'T','o','t','o', '\0'};
Run Code Online (Sandbox Code Playgroud)

在 的情况下c1,它假设您需要附加隐式空值并c1自动设置大小以允许空间,因此如果您使用sizeofstd::extent<>获取 的大小,c1您将看到它是 5 个字节。

Drew 的评论建议解释在调用函数时数组衰减到指针,所以这里是。当你写:

cout << c2;
Run Code Online (Sandbox Code Playgroud)

编译器调用函数std::ostream& operator<<(std::ostream&, const char*)。数组c2 衰减为 a char*,允许匹配和调用函数,但这样做会丢失所有关于文本长度的知识。函数实现要求您遵循在要流式传输的文本之后使用空终止符的约定。如果你想明确控制应该打印多少个字符,你可以使用例如std::cout.write(c2, 3). std::strings 的工作也更直观——初学者应该更喜欢使用std::strings 来存储和操作文本。

  • @user106306可能,您的编译器将“c2”放在堆栈上的“c1”之前,这导致您的堆栈看起来像“TotoToto\0”,以“c2[0]”开头。它使它看起来像“&amp;c2[0]”指向一个以空终止符结尾的字符串,该字符串在空终止符之前包含 8 个字符。编辑:由于这是未定义的行为,因此程序的输出可能会在没有明显原因的情况下随时更改。您不能依赖此布局始终正确。 (2认同)