目录
一、前言
俗话说:“工欲善其事,必先利其器。”对于想要学习C语言的人来说,选择一个合适的编译器是首要任务。在众多编译器中,Visual Studio(简称VS)应用广泛且知名度高。然而,尽管VS功能强大,但在一些方面对新手不太友好。例如在处理函数时,出于安全性考虑,VS并不提倡使用某些C语言标准中的函数,像scanf函数就属于这一类 ,这无疑给初涉C语言学习的新手设置了一定的障碍。今天,我们就来解决在VS中使用scanf会报错这一问题。
二、解决方案
首先,我们先尝试在VS中使用scanf函数,代码如下:
#include <stdio.h>
int main()
{
int n;
printf("请输入n的值:");
scanf("%d",&n);
return 0;
}
运行该代码,会得到如下报错信息:
C4996 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
我们可以翻译一下这句话,它的中文含义是:
“scanf”:此函数或变量可能不安全。建议使用 scanf_s 函数替代它。若要取消此弃用提示,请使用 _CRT_SECURE_NO_WARNINGS 宏。有关详细信息,请查看联机帮助。
从报错信息中我们就可以知道,用两种解决方案,一是使用VS特有的scanf_s函数,这时VS提供的scanf函数的安全版,详细内容等到第三部分再行介绍,现在,我们先来看看第二种解决方案,使用宏定义,就是对报错信息 _CRT_SECURE_NO_WARNINGS进行宏定义,修改后的代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int n;
printf("请输入n的值:");
scanf("%d",&n);
printf("n的值为:%d", n);
return 0;
}
此代码可以正常运行。
三、scanf_s
1.简要介绍
scanf_s 是 scanf 的一种安全版本,主要用于防止缓冲区溢出等安全问题。它是 Microsoft 提供的扩展函数,符合 C11 标准。与 scanf 相比,scanf_s 需要额外的参数来指定输入缓冲区的大小。
2.scanf函数为何不安全
(1)缓冲区溢出风险:在使用scanf
读取字符串时,如果没有对输入字符串的长度进行有效控制,就极易引发缓冲区溢出问题。例如
#include <stdio.h>
int main() {
char str[10];
// 若输入超过9个字符(不包含字符串结束符'\0'),就会发生缓冲区溢出
scanf("%s", str);
printf("你输入的内容是:%s\n", str);
return 0;
}
当用户输入的字符数超出str数组的容量时,多余的字符会覆盖相邻内存空间的数据,这可能导致程序崩溃、产生不可预测的结果,甚至引发安全漏洞,使恶意攻击者能够执行任意代码。
(2)输入类型不匹配:scanf函数根据格式控制字符串来解析输入,如果输入的数据类型与格式控制字符串中指定的类型不匹配,scanf可能无法正确读取输入,还会导致未定义行为。例如:
#include <stdio.h>
int main() {
int num;
// 若输入的不是整数,如输入字符'a',就会导致输入类型不匹配
scanf("%d", &num);
printf("你输入的整数是:%d\n", num);
return 0;
}
当输入非整数时,scanf会将其转换为int类型,但这不仅会使num的值不正确,还可能影响后续scanf函数的执行以及程序的稳定性。(如果输入是浮点数会自动取整舍去小数部分,如果输入是字符类型的话,会打印出一个很奇怪的数字)
3.scanf_s函数的使用方法
在输入整型以及浮点型数据时,scanf与scanf_s使用上并没有区别,代码如下
#include <stdio.h>
int main()
{
int n;
printf("请输入n的值:");
scanf_s("%d",&n);
printf("n的值为:%d", n);
return 0;
}
在读取字符串或字符数组时,scanf_s要求明确指定接收缓冲区的大小。这有助于防止输入的长度超出缓冲区大小,提高程序的安全性。使用方法是在变量后面加上其大小,代码如下
#include <stdio.h>
#include <stdlib.h>
int main() {
char str1[5];
scanf_s("%s", str1, (unsigned)_countof(str1));
// 注意这里的_countof(str)是一个宏,它的值是sizeof(str),包含在stdlib.h中
printf("%s\n", str1);
char str2[5];
scanf_s("%s", str2, 5);
// 数组最后一位需要用来存储字符串结束符\0,所以实际上只能输入4个字符
printf("%s\n", str2);
return 0;
}
如果同时输入多个数组,可采用以下写法
#include <stdio.h>
int main() {
char str1[5];
char str2[5];
scanf_s("%s %s", str1, 5, str2, 5);
printf("%s\t%s\t", str2);
return 0;
}
请勿写成
scanf_s("%s %s", str1, str2, 5, 5);