使用scanf读取多字符串时除最后一个外首字符丢失的问题排查
问题根源:缓冲区溢出引发的未定义行为
你的问题出在字符数组大小不足,导致scanf写入时触发缓冲区溢出,破坏了相邻内存的数据:
- C语言中,字符串必须以
'\0'(空字符)作为结束标记。你定义的char word0[4]这类数组,最多只能容纳3个可见字符加1个'\0'。 - 当你输入4个字符的单词(比如
zxcv)时,scanf("%s")会尝试把4个字符加上'\0'共5个字节写入仅4字节的数组,超出数组范围的字节会覆盖栈上相邻变量的内存。 - 由于栈上局部变量是连续分配的(具体布局由编译器和平台决定),溢出的字节会修改相邻数组的首字符,或者被后续的
scanf写入操作反向覆盖,最终出现你看到的“除最后一个单词外首字符丢失”的现象。
修复方案
- 调整数组大小:将每个字符数组的长度改为5,确保能容纳4个可见字符加
'\0':
char word0[5], word1[5], word2[5];
- 限制输入长度(更安全):在
scanf中指定最大读取字符数,避免溢出。比如数组大小为4时,最多读取3个字符:
scanf("%3s", word0); scanf("%3s", word1); scanf("%3s", word2);
或者数组大小为5时,限制读取4个字符:
scanf("%4s%s%s", word0, word1, word2);
修复后的示例代码
#include <stdio.h> int main() { char word0[5], word1[5], word2[5]; scanf("%4s%4s%4s", word0, word1, word2); printf("word0: %s\n", word0); printf("word1: %s\n", word1); printf("word2: %s\n", word2); }
输入zxcv abcd 1234后,输出会恢复正常:
word0: zxcv word1: abcd word2: 1234
内容的提问来源于stack exchange,提问作者Alison
相关产品推荐
相关产品推荐

