在大小为 10 的 char 数组中输入超过 10 个字符的字符串并输出时,它会显示整个数组而不是前 10 个数组.为什

On inputting a string of more than 10 characters in a char array of size 10 and outputting it, it shows the whole array instead of the first 10. Why?

本文关键字:数组 字符 显示 为什 字符串 char 小为 输入 串并 输出      更新时间:2023-10-16
#include<iostream>
using namespace std;
int main()
{
char d[10];
cout<<"Enter any string which has more than 10 characters in it";
cin>>d;
cout<<"The string you entered is "<<endl;
cout<<d;
return 0;
}

假设您输入了"1234567890123",那么它应该只显示"123456789"而不是您输入的整个内容,但它正在执行后者。

欢迎来到未定义的行为领域。 目前cin使用以下形式的函数:

template< class CharT, class Traits>
basic_istream<CharT,Traits>& operator>>( basic_istream<CharT,Traits>& st, CharT* s );

为了将输入读入数组。 由于它使用指针,因此它不知道您的数组有多大,并且会很高兴地溢出缓冲区,从而导致未定义的行为。

您观察到的症状之一是它将您不允许访问的数据写入内存,但该访问不会导致错误。 当你去读取数组的内容时,你会得到完整的输入,即使你不应该这样做。 但是,您不能依赖此行为。 该程序可能会崩溃,或者发生其他任何事情。 未定义的行为意味着任何结果都可能发生。

从 C++ 20 开始,使用数组时将不再发生这种情况。 函数的签名将更改为

template< class CharT, class Traits, std::size_t N >
basic_istream<CharT,Traits>& operator>>( basic_istream<CharT,Traits>& st, CharT (&s)[N] );

由于它通过引用获取数组,因此它知道它的大小,并且可以阻止自己溢出缓冲区。


应该注意的是,这是一个重大更改。 代码类似

auto p = new char[100];
std::cin >> std::setw(20) >> p;

这是合法的C++17 代码不会在 C++20 中编译p因为 不是数组。 您可以在此处查看有关此更改的论文:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0487r1.html


如果您切换到使用std::string则根本不需要担心这一点,因为std::string会增长以适应输入的输入。 那会给你

#include<iostream>
#include <string>
int main()
{
std::string input;
std::cout << "Enter any string which has more than 10 characters in it";
std::getline(std::cin, input);
std::cout << "The string you entered is n" << input;
return 0;
}

在C++中,数组和指针是可以互换的。

char* a;
char b[123];
// these two call the same function.
cin>>a;
cin>>b;

流运算符>>不知道您在 char* 指向的任何地方分配了多少存储空间,它只是开始写入直到完成。

现在想象一下,当你遇到这样的案例时会发生什么

char foo[2];
bool bar = false;
cin>>foo;
if (bar)
{
...
}

foobar在堆栈上彼此相邻。 当cin>>写过foo结束时,它会踩踏所有为bar保留的内存。

如果您听说过"堆栈缓冲区溢出"攻击,这就是他们正在谈论的事情,顺便说一下(我认为(stackoverflow.com 它的名字。 充分覆盖堆栈上的缓冲区以将坏事写入堆栈,例如更改函数将返回到的位置(到同一溢出的不同部分(,以及您可能不希望计算机执行的一堆指令。