[TOC]
# vs中c4996错误
由于微软在vs2013中不建议使用c的传统函数scanf,strcpy,sprintf等,所以直接使用这些库函数会提示c4996错误,在源文件中添加一下指令就可以避免错误提示
~~~
这个宏定义一定要放在.c文件的第一行
#define _CRT_SECURE_NO_WARNINGS
或者放在main函数之前include下面
pragma warning(disable:4996)
~~~
scanf并不会直接读入用户输入完成的回车键,而是最后自动补一个0,这样才是完整的字符串,scanf并不检查参数char的数组下标,用户输入多少,scanf就往数组中放入多少,一旦用户输入的过多,会导致内存错误
# 安全函数
VS(Visual Studio)下编译程序,如果使用了 scanf()、gets()、strcpy()、strcat() 等与字符串读取或操作有关的函数,有时候VS会报错,提示该函数可能不安全,并且建议替换为带有`_s`后缀的安全函数
scanf()、gets()、fgets()、strcpy()、strcat() 等都是C语言自带的函数,它们都是标准函数,但是它们都有一个缺陷,就是不安全,可能会导致数组溢出或者缓冲区溢出,让黑客有可乘之机,从而发起“缓冲区溢出”攻击。
scanf\_s()、gets\_s()、fgets\_s()、strcpy\_s()、strcat\_s() 是微软自己发明的安全函数,它们仅适用于 VS,在其它编译器下无效。这些安全函数在读取或操作字符串时要求指明长度,这样一来,过多的字符就会被过滤掉,避免了数组或者缓冲区溢出。
下面我们以 scanf\_s() 为例来讲解。
scanf() 在读取字符串时不会检查字符个数,它不知道数组或缓冲区到底能容纳多少个字符,例如:
~~~
char buf[5]={0};
scanf(“%s”, buf);
~~~
当用户输入`abcdeABCDE`这10个字符时,scanf() 会全部读取,并放入 buf 中,不过 buf 最多只能存储 5 个字符,不足以容纳用户输入的全部数据,所以多出来的 5 个字符就会使用 buf 后面的内存,而 buf 后面的内存可能没有使用权限,或者已经被别的数据占用,这就导致程序在运行时可能会出现不可预知的错误。
最要命的是,这种错误只能等到程序运行时才能检测出来,在编译期间根本无法检测;一旦检测出来只有一种后果,就是程序被操作系统终止,也就是我们常说的“程序崩溃”。
更改上面的代码,使用 scanf\_s() 代替 scanf():
~~~
char buf[5] = {0};
scanf_s(“%s”, buf, 5);
~~~
scanf\_s() 最后一个参数用来指明数组或者缓冲区的大小,假设它的值为 n,那么最多只允许读取 n-1 个字符(因为最后要存储`'\0'`),多出来的字符就不再读取了,这样就可以避免读入过多的字符。与 scanf() 相比,scanf\_s() 显然更加安全。
但是,安全函数不利于大家学习,它们不但使用麻烦,而且也不被绝大多数教程采用。另外,安全函数是微软自己发明的,只适用于 VS 编译器,在其他编译器下无效。
# 如何取消安全函数的限制
我们通过对 VS 做适当的设置,让它不再强制使用安全函数,从而可以使用 scanf()、gets()、fgets()、strcpy()、strcat() 等C语言的标准函数去编程。
VS 之所以会提示使用安全函数,是因为它进行了SDL检查(安全性开发生命周期检查),只要将它取消就可以了。
1) 菜单栏中选择 “项目 --> xxx属性”(xxx为创建的项目名称),或者直接按下组合键“Alt+F7”,如下图所示:

2) 此时会弹出如下图所示的一个对话框,选择“C/[C++]--> SDL检查”,将“是”改为“否”,如下图所示:

3、最后点击“确定”按钮,重新运行程序,你会发现程序可以正常运行了。
另外,VS2010、VS2015 等低版本的 VS 可以在创建项目之处就取消 SDL 检查(如下图所示),但是到了 VS2017 时就不行了,创建项目时没有这个选项了,只能在创建项目完成以后再按照以上步骤取消 SDL 检查

- c语言
- 基础知识
- 变量和常量
- 宏定义和预处理
- 随机数
- register变量
- errno全局变量
- 静态变量
- 类型
- 数组
- 类型转换
- vs中c4996错误
- 数据类型和长度
- 二进制数,八进制数和十六进制数
- 位域
- typedef定义类型
- 函数和编译
- 函数调用惯例
- 函数进栈和出栈
- 函数
- 编译
- sizeof
- main函数接收参数
- 宏函数
- 目标文件和可执行文件有什么
- 强符号和弱符号
- 什么是链接
- 符号
- 强引用和弱引用
- 字符串处理函数
- sscanf
- 查找子字符串
- 字符串指针
- qt
- MFC
- 指针
- 简介
- 指针详解
- 案例
- 指针数组
- 偏移量
- 间接赋值
- 易错点
- 二级指针
- 结构体指针
- 字节对齐
- 函数指针
- 指针例子
- main接收用户输入
- 内存布局
- 内存分区
- 空间开辟和释放
- 堆空间操作字符串
- 内存处理函数
- 内存分页
- 内存模型
- 栈
- 栈溢出攻击
- 内存泄露
- 大小端存储法
- 寄存器
- 结构体
- 共用体
- 枚举
- 文件操作
- 文件到底是什么
- 文件打开和关闭
- 文件的顺序读写
- 文件的随机读写
- 文件复制
- FILE和缓冲区
- 文件大小
- 插入,删除,更改文件内容
- typeid
- 内部链接和外部链接
- 动态库
- 调试器
- 调试的概念
- vs调试
- 多文件编程
- extern关键字
- 头文件规范
- 标准库以及标准头文件
- 头文件只包含一次
- static
- 多线程
- 简介
- 创建线程threads.h
- 创建线程pthread
- gdb
- 简介
- mac使用gdb
- setjump和longjump
- 零拷贝
- gc
- 调试器原理
- c++
- c++简介
- c++对c的扩展
- ::作用域运算符
- 名字控制
- cpp对c的增强
- const
- 变量定义数组
- 尽量以const替换#define
- 引用
- 内联函数
- 函数默认参数
- 函数占位参数
- 函数重载
- extern "C"
- 类和对象
- 类封装
- 构造和析构
- 深浅拷贝
- explicit关键字
- 动态对象创建
- 静态成员
- 对象模型
- this
- 友元
- 单例
- 继承
- 多态
- 运算符重载
- 赋值重载
- 指针运算符(*,->)重载
- 前置和后置++
- 左移<<运算符重载
- 函数调用符重载
- 总结
- bool重载
- 模板
- 简介
- 普通函数和模板函数调用
- 模板的局限性
- 类模板
- 复数的模板类
- 类模板作为参数
- 类模板继承
- 类模板类内和类外实现
- 类模板和友元函数
- 类模板实现数组
- 类型转换
- 异常
- 异常基本语法
- 异常的接口声明
- 异常的栈解旋
- 异常的多态
- 标准异常库
- 自定义异常
- io
- 流的概念和类库结构
- 标准io流
- 标准输入流
- 标准输出流
- 文件读写
- STL
- 简介
- string容器
- vector容器
- deque容器
- stack容器
- queue容器
- list容器
- set/multiset容器
- map/multimap容器
- pair对组
- 深浅拷贝问题
- 使用时机
- 常用算法
- 函数对象
- 谓词
- 内建函数对象
- 函数对象适配器
- 空间适配器
- 常用遍历算法
- 查找算法
- 排序算法
- 拷贝和替换算法
- 算术生成算法
- 集合算法
- gcc
- GDB
- makefile
- visualstudio
- VisualAssistX
- 各种插件
- utf8编码
- 制作安装项目
- 编译模式
- 内存对齐
- 快捷键
- 自动补全
- 查看c++类内存布局
- FFmpeg
- ffmpeg架构
- 命令的基本格式
- 分解与复用
- 处理原始数据
- 录屏和音
- 滤镜
- 水印
- 音视频的拼接与裁剪
- 视频图片转换
- 直播
- ffplay
- 常见问题
- 多媒体文件处理
- ffmpeg代码结构
- 日志系统
- 处理流数据
- linux
- 系统调用
- 常用IO函数
- 文件操作函数
- 文件描述符复制
- 目录相关操作
- 时间相关函数
- 进程
- valgrind
- 进程通信
- 信号
- 信号产生函数
- 信号集
- 信号捕捉
- SIGCHLD信号
- 不可重入函数和可重入函数
- 进程组
- 会话
- 守护进程
- 线程
- 线程属性
- 互斥锁
- 读写锁
- 条件变量
- 信号量
- 网络
- 分层模型
- 协议格式
- TCP协议
- socket
- socket概念
- 网络字节序
- ip地址转换函数
- sockaddr数据结构
- 网络套接字函数
- socket模型创建流程图
- socket函数
- bind函数
- listen函数
- accept函数
- connect函数
- C/S模型-TCP
- 出错处理封装函数
- 多进程并发服务器
- 多线程并发服务器
- 多路I/O复用服务器
- select
- poll
- epoll
- epoll事件
- epoll例子
- epoll反应堆思想
- udp
- socket IPC(本地套接字domain)
- 其他常用函数
- libevent
- libevent简介