核心结论就是 gets 是 C 语言标准库 stdio.h 里面的字符串输入函数,作用是从标准输入也就是键盘读取一整行字符,一直读到回车换行符为止,并且把换行符替换成字符串结束标记 0,存入字符数组当中,它和 scanf 的 s 格式符最大区别就是 gets 可以读取带空格的整行内容,scanf 遇到空格就会停止读取,但是 gets 最大的致命缺陷就是没有长度限制,不会检查字符数组容量,用户输入字符超过数组大小就会造成缓冲区溢出,引发程序崩溃甚至安全漏洞,所以 C11 标准已经正式删除 gets 函数,现在新项目不推荐继续使用,推荐替换成 fgets 函数。之所以早期教材会讲解 gets,是因为它语法简单,读取整行字符串非常方便,适合入门练习题,但是这个无边界读取的设计缺陷,在现代编程当中属于高危函数,考试如果题目要求写 gets,按照知识点作答,实际工程开发一定要避开。
一 gets 基础语法
函数原型
char 星号 gets 括号内 char 星号 str
参数 str 是已经提前定义好的字符数组首地址
返回值,读取成功返回传入的 str 指针,如果读取失败或者读到文件结束,返回空指针 NULL
基础执行逻辑
程序执行 gets 之后阻塞等待键盘输入,用户输入一行文字,按下回车,gets 读取全部字符,包含中间空格,直到遇到换行符,丢弃换行符,在末尾自动补上 0 结束符,形成 C 语言标准字符串。
二 gets 和 scanf s 格式符对照表
| 对比项目 | gets 函数 | scanf s 格式符 |
|---|---|---|
| 读取终止条件 | 读到回车换行停止 | 遇到空格回车制表符就停止 |
| 是否支持空格 | 支持整行带空格 | 不支持,空格截断 |
| 长度校验 | 没有长度校验,会溢出 | 同样没有长度限制,依然危险 |
| 标准状态 | C11 已经移除 | 仍然保留 |
三 详细使用步骤
第一步 源文件引入 stdio.h 头文件
第二步 提前定义字符数组,比如 char str 等于 数组大小
第三步 书写 gets str,传入字符数组名,数组名本身就是首地址,不需要再加取地址符号
第四步 程序运行等待用户输入,输入整行内容按下回车,字符串存入数组
第五步 后续代码可以使用 printf 输出,或者调用 strlen strcmp 这类字符串函数处理这个字符串
第六步 如果是课程考试题目,按照题目要求书写 gets,如果是实际开发,替换成 fgets,增加长度限制防止溢出
四 深度重点知识
缓冲区溢出原理,字符数组在内存是连续空间,如果输入字符数量超过数组分配的字节,多余字符就会覆盖数组后面相邻内存,破坏其他变量,严重的时候可以篡改返回地址,属于经典缓冲区溢出安全漏洞,这也是 C11 删除 gets 最核心原因。
fgets 替代写法,fgets str 数组长度 stdin,这个函数会读取指定最大长度字符,并且会把回车换行符保留在字符串里面,使用的时候需要手动处理末尾换行符,安全性远高于 gets。
gets 读取成功之后返回值就是传入的数组指针,可以判断返回值是否为 NULL,判断读取是否出错。
gets 读取的字符串是 char 类型数组,属于 C 语言以 0 结尾的字符串,必须保证数组空间足够存放输入字符加上末尾的 0。
五 高频踩坑要点
第一 继续在现代编译器使用 gets,部分编译器已经不再提供 gets,编译报错或者警告。
第二 数组开的太小,输入过长造成缓冲区溢出,程序随机崩溃。
第三 混淆 gets 和 scanf s,以为 scanf 可以读取带空格整行。
第四 忘记 C 语言字符串必须带 0 结束标记,gets 虽然自动补 0,但是数组容量不足的时候依然会溢出。
第五 多输入场景,gets 和 scanf 混用的时候,输入缓冲区残留回车,出现读取异常。
问题 1 c 语言中的 gets 函数的详细用法里面为什么 C11 删掉 gets
回答 1 c 语言中的 gets 函数的详细用法核心缺陷是没有长度限制,输入超长会发生缓冲区溢出,存在安全风险,所以 C11 标准移除 c 语言中的 gets 函数的详细用法对应的 gets,推荐改用 fgets。
问题 2 c 语言中的 gets 函数的详细用法能不能读取带空格字符串
回答 2 c 语言中的 gets 函数的详细用法可以读取带空格的整行字符串,遇到回车才停止读取,这也是 c 语言中的 gets 函数的详细用法相比 scanf s 格式符最大优势。
问题 3 c 语言中的 gets 函数的详细用法返回值是什么
回答 3 c 语言中的 gets 函数的详细用法读取成功返回字符数组指针,读取失败或者遇到文件结束标记的时候,c 语言中的 gets 函数的详细用法返回 NULL 空指针。
本文内容仅作为 C 语言 gets 函数相关语法学习参考,gets 属于已经废弃高危函数,实际项目开发禁止使用,不同编译器对 gets 支持情况存在差异,本文不对按照本文代码运行产生的缓冲区溢出程序崩溃等问题承担相关责任。


