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

C语言中%5c格式控制符导致输出异常的原因探究

scanf格式符误用导致的异常输出分析
#include <stdio.h>

int main() {
    int y = 0, w = 0;
    scanf("%d %5c", &y, &w);
    printf("%d,%c\n", y, w);
    return 0;
}

异常现象

  • 输入2000 12345,输出1845,1
  • 输入1000 12345,输出821,1
  • 输入2000 23456,输出1846,2
  • 将%5c改为%4c后,输入2000 12345输出2000,1

问题根源与数值解析

  1. 类型不匹配引发缓冲区溢出
    变量w是int类型(通常占4字节),但scanf中使用了%c格式符配合%5c——这表示连续读取5个字符并写入目标地址。由于w仅能容纳4字节数据,前4个字符填满w的内存后,第5个字符会越界写入相邻变量y的内存空间,直接篡改y的原始值。

  2. 奇怪数值的具体来源
    以输入2000 12345为例:

    • %d读取2000后,跳过空格,%5c读取1、2、3、4、5这5个字符。
    • 前4个字符按小端序(多数系统的字节存储规则)写入w的4字节,printf("%c", w)会取w的最低字节(即'1'的ASCII码0x31),因此输出字符为1。
    • 第5个字符'5'的ASCII码是0x35,会覆盖y的最低字节:原y=2000的十六进制为0x000007D0,最低字节0xD0被替换为0x35,新值为0x00000735,转换成十进制就是1845。

    其他数值同理:

    • 输入1000 12345:1000的十六进制是0x000003E8,最低字节0xE8被替换为0x35,得到0x00000335(十进制821)。
    • 输入2000 23456:第5个字符是'6'(ASCII码0x36),替换后y的十六进制为0x00000736(十进制1846)。
  3. 改为%4c后恢复正常的原因
    %4c读取4个字符,刚好填满w的4字节内存,不会发生越界写入,因此y的内存未被篡改,保持初始读取的2000不变,输出自然正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 14:05:16