You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ istream读入char*在C++20下触发C2679编译报错问题

关于is >> buffer写法的说明

在使用C++20标准编译书中这段代码时,会抛出如下编译错误:

C2679 binary '>>': no operator found which takes a right-hand operand of type 'char *' (or there is no acceptable conversion)

代码在旧标准下的合法性与运行逻辑

这段代码不是作者笔误,在C20标准发布前,代码完全符合C标准规范。
C++17及更早版本的标准库为std::istream的流提取运算符>>提供了接收char*类型右操作数的重载,配合前置的is.width(max)调用,运行逻辑和书中注释完全一致:

  • 自动跳过输入流起始位置的所有空白字符(空格、制表符、换行符等)
  • 从第一个非空白字符开始逐字符读取,直到遇到下一个空白字符停止
  • 受width(max)设置约束,最多读取max-1个字符,预留1字节位置用于自动追加C风格字符串结束符\0
  • 读取完成后自动在缓冲区末尾写入\0,保证缓冲区内容是合法的以空字符结尾的字符串
  • 最终返回流对象本身,支持链式调用
    这也解释了为什么在C14、C17标准下测试时,代码可以正常编译运行。

C++20下编译报错的原因

C20标准正式移除了operator>>对char*类型的支持,这个改动是为了从标准层面规避缓冲区溢出风险:
接收裸char*的重载无法在编译期感知缓冲区的实际大小,完全依赖开发者手动调用width()设置读取上限,一旦开发者遗漏这一步,输入长度超过缓冲区大小时就会发生越界写,是非常常见的内存安全漏洞来源。
C
20保留了对固定长度字符数组char[N]的流提取支持,编译器可以在编译期获取数组长度自动做边界校验,安全性远高于裸指针传参,因此直接删除了风险更高的char*重载,这就是C++20环境下(无论VS2022、GCC还是Clang)出现编译错误的根本原因。

适配C++20的修改方式

如果需要在C++20及后续标准中实现书中代码的功能,推荐两种安全的改法:

  • 改法1:使用模板接收固定长度字符数组,自动推导缓冲区长度,保留原代码C风格缓冲区的逻辑
template<std::size_t N>
istream& read_word(istream& is, char (&buffer)[N])
{
    is.width(N);    // 自动使用数组长度作为读取上限,不需要额外传max参数
    is >> buffer;
    return is;
}
  • 改法2:使用std::string接收输入,完全不需要手动管理缓冲区大小,是现代C++的推荐写法
istream& read_word(istream& is, std::string& str)
{
    is >> str;
    return is;
}

如果只是为了跑通书中的示例代码,直接将编译标准切换到C++17也可以正常运行,但不建议在新写的代码中继续使用裸char*做流输入参数。


内容的提问来源于stack exchange,提问作者CPPL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 11:15:42