为什么C语言中scanf读取数组后访问元素会触发段错误?
段错误原因分析及修复建议
一、触发段错误的核心原因
1. 未限制输入长度导致缓冲区溢出
你声明的input1是栈上分配的30字节字符数组,而scanf("%s", input1)没有设置输入长度限制。如果输入的字符数超过29(C字符串需要末尾的\0作为结束标记,所以最多只能存29个有效字符),超出的内容会直接写入数组之外的栈内存区域,破坏栈帧的结构(比如覆盖函数返回地址、其他变量的存储空间)。
这种情况下,printf("%s", input1)可能还能暂时输出内容(因为字符串的\0可能还没被完全覆盖),但当执行到char current = input1[0];时,栈已经被破坏,数组的起始地址或内存内容已经异常,从而触发段错误。
2. 循环逻辑存在无限遍历风险
如果缓冲区溢出导致字符串的\0结束符被覆盖,你的循环会持续执行:counter不断递增,反复访问input1[counter],最终越界访问到非法内存区域,同样会触发段错误。
二、修复方案
限制
scanf的输入长度
将scanf("%s", input1)修改为scanf("%29s", input1),强制最多读取29个字符,预留一个字节给\0,从根源避免缓冲区溢出。优化循环遍历逻辑
改用指针遍历的方式,更简洁且避免计数器越界的问题,同时修正isdigit的参数类型(避免传入负数值导致未定义行为):#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> int main(){ char input1[30]; scanf("%29s", input1); printf("%s\n", input1); char *current = input1; while (*current != '\0'){ // 把char转为unsigned char,避免isdigit处理负数值 if (isdigit((unsigned char)*current) || strchr("+-*/", *current)){ current++; } else { printf("invalid input\n"); exit(1); } } return 0; }
内容的提问来源于stack exchange,提问作者Kunait
相关产品推荐
相关产品推荐

