【问题标题】:Difference between scanf and scanf_sscanf 和 scanf_s 的区别
【发布时间】:2014-02-21 11:19:16
【问题描述】:

scanfscanf_s 有什么区别?在大学里,我被教过,我正在使用scanf,但在我的个人计算机上,Visual Studio 不断发送此警告。

 error C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead.

我必须将所有scanf 更改为scanf_s,否则程序将无法构建。 (我使用的是 Visual Studio 2013)

【问题讨论】:

标签: c visual-studio scanf tr24731


【解决方案1】:

这是一个专门属于微软编译器的函数。

scanf 最初只是读取您键入的任何控制台输入并将其分配给一种变量。

如果您有一个名为first_name[5] 的数组并且您使用scanf 表示“Alex”,则没有问题。如果您有相同的数组并分配“Alexander”,您可以看到它超过了该数组包含的 5 个插槽,因此 C 仍会将其写入不属于该数组的内存中,并且它可能会或可能不会使程序崩溃,取决于是否有东西试图访问和写入不属于 first_name 的内存插槽。这就是scanf_s 的用武之地。

scanf_s 有一个参数(参数),您可以在其中指定缓冲区大小并实际控制输入的限制,这样您就不会崩溃整个建筑物。

【讨论】:

  • “您可以在哪里指定缓冲区大小”-> 这是错误的。更正:“您可以在其中指定缓冲区大小,并且必须为 c、C、s、S 或 [ 类型的所有输入参数指定它。”因此,简单地将后缀“_s”添加到使用 scanf("...%s...", ...) 的程序会导致程序编译时没有警告,但什么也不做,因为 0 大小的缓冲区是假设并且没有数据被读入。
  • 实际上,在 Visual Studio 中,只要在没有缓冲区长度参数的情况下使用 %s%c,编译器就会合规。
  • _s 函数现在是 C11 的一部分并且可移植。
  • _s 函数现在是 C11 的一部分并且可移植。 附件 K 是可选的,Microsoft 实现不可移植。 Field Experience With Annex K — Bounds Checking Interfaces:“Microsoft Visual Studio 实现了 API 的早期版本。但是,实现不完整,既不符合 C11 也不符合原始 TR 24731-1。......由于与规范的大量偏差, Microsoft 实施不能被视为符合标准或可移植。”
【解决方案2】:

scanf_s() 未在 C99 标准(或以前的标准)中描述。

如果您想使用面向 C99(或以前)的编译器,请使用 scanf()

对于 C11 标准(以及最终的更高版本)scanf_s()scanf() 更难使用,以提高防止缓冲区溢出的安全性。

C11fscanf_s():http://port70.net/~nsz/c/c11/n1570.html#K.3.5.3.2

~~~~~~~~~~~~~~~~

如果您的 C99 编译器带有提供 scanf_s() 作为扩展的附加功能,并且不介意失去可移植性,请查看您的编译器文档。

【讨论】:

  • 请注意,C11 标准的附件 K 是可选的。一个实现可以声称是 C11 并且不提供 scanf_s()(您可以使用 #if defined(__STDC_LIB_EXT1__) 检查)。
  • 我不会称之为“更难”使用。只需在扫描字符串 och 字符时提供缓冲区大小即可,无论如何您都应该这样做!
【解决方案3】:

要避免此错误,您可以做的是在 之间粘贴内容: <_crt_secure_no_warnings> 到一个地方。 要到达该位置,请在解决方案资源管理器中右键单击您的项目,然后单击属性。然后转到配置属性,然后是 c/c++,然后是预处理器。然后在预处理器定义中,在所有内容之后,添加分号并将内容粘贴进去。然后按应用并确定。你的问题应该已经解决了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-18
    • 1970-01-01
    • 2010-11-18
    • 1970-01-01
    • 1970-01-01
    • 2016-12-05
    • 1970-01-01
    相关资源
    最近更新 更多