C语言中定义长度为5的字符串为何能接收更长的scanf输入?
现象原因
C 标准库的scanf函数使用%s格式符读取字符串时,默认不会对输入长度做边界检查。你定义的char word[5]仅分配了5字节的连续内存空间,按C语言字符串规则最多只能存储4个有效字符 + 1个末尾结束符\0。
当你输入长度超过4的字符串时,超出数组边界的内容会被写入数组后续的内存地址,这属于典型的缓冲区溢出,是C语言中的未定义行为。你当前测试时能正常打印完整字符串,只是刚好溢出覆盖的内存区域暂时没有被程序其他逻辑、操作系统占用,没有触发段错误、数据篡改等异常,但这种写法存在严重安全隐患,随时可能导致程序崩溃、敏感数据泄露甚至被恶意代码利用。
限制输入长度的方案
- 方案1:给
%s格式符增加长度限定
直接在%和s之间填写最大读取的有效字符数,数值必须比数组总长度小1(预留1字节存储\0)。你的数组长度为5,写法如下:// 最多读取4个有效字符,自动忽略超出部分 scanf("%4s", word); - 方案2:使用更安全的
fgets函数读取输入fgets默认要求传入缓冲区的最大长度,会自动预留\0的存储空间,避免溢出:// 第二个参数直接传数组总长度即可,fgets会自动处理结束符 fgets(word, sizeof(word), stdin); // 可选:如果要去掉fgets读取到的末尾换行符,增加以下逻辑 if (word[strlen(word)-1] == '\n') { word[strlen(word)-1] = '\0'; }
注意:完全不做边界检查的
gets函数已经被C标准正式移除,任何场景都不建议使用。
修正后的完整代码示例
#include <stdio.h> #include <string.h> int main() { char word[5]; printf("Enter word: "); // 限定最多读4个字符 scanf("%4s", word); printf("Word: %s\n", word); strlwr(word); printf("To Lower: %s\n", word); return 0; }
内容的提问来源于stack exchange,提问作者Satyajit Roy
相关产品推荐
相关产品推荐

