我们先说一说scanf的运行机制是怎么样的:
如下图(先不解释为什么没有带参数),对于字符串的输入,这里的scanf是会在确定了arr这个地址之后,按照arr这个数组的类型也就是char类型,一个个以char为大小的单位往下输入字符,直到我们回车才停止。
而有些小伙伴可能也会问道:在这个scanf里arr跟&arr的跨度不是不一样吗(参照上一篇博客),这就是上面的scanf运行机制问题,所以在scanf对字符串输入中,arr与&arr是没有区别的!
接下来就是中心问题了:为什么要在arr后面加一个参数?这是一个安全问题,因为我们在用scanf输入字符串的时候,编译器不知道我们给它安排的空间有多大,所以只要我们不停地写,它就能够不停地输入,这会造成输入的数据过大导致数据溢出的隐患(即输入过多的数据放在超过数组空间大小的其他地方),这就会有数据丢失的风险。
所以在vs2015之后,scanf因为这个安全问题被改成了scanf_s(这也是用scanf会报错的原因),从此之后,scanf_s在输入字符串的时候,是需要在数组地址后面再加一个参数作为限制输入大小的值。
值得一提的是,在我们用#define _CRT_SECURE_NO_WARNINGS 把这个scanf的报错警告去除掉之后,会发现我们是不需要再输入参数的,而scanf_s则是一定需要参数的。