C语言递归实现字符反转:scanf段错误、getchar正常的原因解析
递归字符反转代码中scanf触发段错误的原因解析
核心问题:类型不匹配+scanf的EOF处理行为
1. EOF的本质
EOF是C标准定义的int类型常量,值通常为-1。而代码中用char ch存储读取的字符,这就埋下了类型不匹配的隐患:
- 如果系统中
char是有符号类型,-1可以被存入ch; - 如果是无符号类型,-1会被转换为
UCHAR_MAX(比如255),此时ch永远不可能等于EOF(int类型的-1)。
2. getchar()能正常运行的原因
getchar()的返回值是int类型:
- 读取正常字符时,返回字符的ASCII值(转换为int);
- 到达EOF或读取失败时,返回
EOF(int的-1)。
当输入结束时,getchar()返回EOF并赋值给char ch:
- 若
char是有符号类型,ch会被设为-1,此时ch == EOF的判断成立,递归终止; - 即使
char是无符号类型,部分环境的输入结束处理逻辑可能让递归提前终止(但本质属于未定义行为,只是恰好正常运行)。
3. scanf("%c", &ch)触发段错误的原因
scanf的行为和getchar()有关键区别:
- 当输入到达EOF时,
scanf("%c", &ch)会返回EOF,但不会修改ch的内存值。而代码中char ch是未初始化的局部变量,值为随机垃圾值。 - 如果这个随机值不等于
EOF(-1),递归会无限调用,每次递归都会在栈上创建新的ch变量,最终导致栈溢出,触发段错误。 - 若系统中
char是无符号类型,ch在和EOF比较时会被提升为unsigned int,此时ch的值永远是正数,不可能等于-1,递归会无条件无限进行,必然触发栈溢出。
修复方案
要解决这个问题,需要从两个方面修正:
- 把
ch的类型改为int,匹配EOF的类型; - 检查
scanf的返回值,而不是只判断ch的值:
#include <stdio.h> void reverse() { int ch; // 检查scanf的返回值,判断是否到达EOF if (scanf("%c", &ch) == EOF) { return; } reverse(); printf("%c", ch); } int main() { reverse(); return 0; }
内容的提问来源于stack exchange,提问作者Ayush
相关产品推荐
相关产品推荐

