C语言for循环仅执行一次的问题原因排查
循环提前终止的根因定位
这段代码一共有3处会直接导致执行异常、循环中断的错误,按影响优先级排序:
scanf传参错误,触发内存访问崩溃scanf读取值时要求传入变量的内存地址,你写的scanf(" %d",student[i].math);直接传入了int类型的成员值,而非地址,程序执行到这行时会把用户输入的整数写入一个随机的非法内存地址,直接触发段错误,第一次循环还没走完就会异常退出,这是循环只执行一次的最常见原因。修正方式是传入成员地址:scanf(" %d", &student[i].math);fflush(stdin)属于标准未定义行为
C语言标准仅规定fflush作用于输出流时的行为,对输入流调用fflush的效果完全取决于编译器实现:在MSVC下可能会清空输入缓冲区,但在GCC、Clang等多数编译器下这行代码没有任何效果,输入完分数后残留的换行符会留在缓冲区中,下一次循环调用输入函数时会直接读到这个空换行,导致输入逻辑错乱,循环意外终止。
正确的缓冲区残留清空写法如下,不要用fflush(stdin):int ch; while ((ch = getchar()) != '\n' && ch != EOF);- 使用了已被废弃的不安全函数
gets()gets()不会限制输入长度,只要输入的姓名字符数超过student[i].name数组的长度,就会发生栈溢出,直接篡改内存中相邻的循环变量i、结构体其他成员的值,轻则导致循环计数错误提前终止,重则直接程序崩溃。C11标准已经正式移除了这个函数,替换为带长度限制的fgets即可:fgets(student[i].name, sizeof(student[i].name), stdin); // 手动去除fgets读入的末尾换行符 student[i].name[strcspn(student[i].name, "\n")] = '\0';
内容的提问来源于stack exchange,提问作者Kevin Chen
相关产品推荐
相关产品推荐

