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

为何scanf_s写入const char*指向内存时两段代码表现不同?

C++两段同逻辑代码运行差异的根本原因

首先明确:两段代码的const修饰的目标存储区域属性完全不同,这是表现差异的核心。

第一段代码可运行的原因

#include <iostream>
using namespace std;

int main()
{
  // 注:原代码存在笔误,数组名itemss和后续使用的items不统一,属于手误不影响核心逻辑
  const char items[8] = "1234567";
  const char* item = items;

  scanf_s("%s", item, 8);
  printf(item);

  return 0;
}
  • 这里的const char items[8]是栈上分配的局部数组,栈内存本身的页属性是可读写的。
  • 此处的const仅为编译期语法限定:仅限制你直接通过items变量名修改数组内容,不会改变内存本身的读写权限。
  • scanf_s接收指针参数时会丢弃const类型限定,相当于绕过了编译期的const检查,直接向可读写的栈内存写入数据,自然不会触发运行时错误。
    注意:这段代码本质是未定义行为,能正常运行只是当前编译环境、运行环境下的偶然表现,不能保证所有场景下都正常执行。

第二段代码触发段错误的原因

#include <iostream>
using namespace std;

int main()
{  
    const char* item = "1234567";

    scanf_s("%s", item, 8);
    printf(item);

    return 0;
}
  • 这里的"1234567"是C++标准规定的字符串字面量,会被编译器分配到进程地址空间的只读数据段(.rodata段),该段内存的页表属性被操作系统标记为只读,任何写入操作都会触发硬件级别的内存保护异常,也就是段错误。
  • 此处的const只是语法上符合字符串字面量的类型要求,哪怕你去掉const写成char* item = "1234567"(C++11之前允许这种隐式转换),写入操作依然会触发段错误,和const修饰符无关,核心是底层内存本身不可写。

核心差异总结

  • 栈上const数组的const是语法层面的编译期检查,不改变内存的可读写属性,绕过检查后写入可以执行。
  • 字符串字面量的底层存储本身就是只读的,属于运行时的硬件/操作系统级别的保护,任何写入操作都会报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 21:33:02