C语言罗马数字转换程序中scanf导致for循环异常原因求解
问题根源分析
你遇到的异常本质是栈缓冲区溢出导致的未定义行为,核心错误出在scanf("%s", &numeral)这行代码:
%s是字符串输入格式符,会自动在读取到的内容末尾追加一个ASCII为0的\0结束符,哪怕你只输入1个字符,最终也会写入2字节数据到目标地址- 你定义的
numeral是单字节char类型变量,仅能存储1字节数据,多出来的\0会越界写入栈上的相邻内存空间,极有可能覆盖循环变量i或者其他栈上数据,直接导致循环逻辑混乱、程序阻塞甚至崩溃。
为什么加了返回值赋值后看起来正常了?
这完全是栈布局变化带来的巧合:
你新增char snf变量后,栈上的变量排布发生了改变,原本会覆盖循环变量的\0结束符,刚好写入了snf的内存空间,没有破坏核心的循环逻辑,所以看起来运行正常,但这本质还是错误的写法,换编译器、换编译参数甚至换运行环境都有可能再次出现异常。
正确修复方案
你需要读取单个字符,应该用%c格式符,注意%c前面要加一个空格,用来跳过输入缓冲区里残留的换行符、空格等空白字符(这些残留来自你之前输入数字后按的回车、每次输入罗马字符后按的回车):
把原来的
scanf("%s", &numeral);
替换为
scanf(" %c", &numeral);
就可以完全解决问题,且符合C语言标准规范,不会出现未定义行为。
内容的提问来源于stack exchange,提问作者Morphii
相关产品推荐
相关产品推荐

