忽略返回值(C编程)

时间:2018-09-07 14:22:20

标签: c

几天前,我才刚开始学习C编程,我正在从Kattis(open.kattis.com)网站上尝试一些问题。在我不太了解这意味着什么的过程中,我想到了这个问题。

//two stones

#include <stdio.h>

int main()
{ 
int n,x=2;

printf("The number of stones placed on the ground is ");
scanf("%d",&n);

if (n%x != 0)
{
    printf("The winner of the game is Alice! \n");
}
else
{
    printf("The winner of the game is Bob! \n");
}
return 0;
}

出现了>>

  

警告:忽略使用属性warn_unused_result声明的scanf返回值[-Wunused-result]   关于scanf(“%d”,&n);

任何人都可以解释这是什么问题以及如何纠正此问题?谢谢。

5 个答案:

答案 0 :(得分:3)

scanf的返回值指示成功:

C标准; §7.19.6.4.3

  

如果在输入失败之前发生输入失败,scanf函数将返回宏EOF的值   任何转换。否则,scanf函数返回输入项的数量   分配的数量,该数量可能少于所提供的数量,如果为早,则为零   匹配失败。

如果在调用scanf的过程中有一个带有格式说明符的格式字符串,则可以检查scanf是否已成功从stdin接收到该类型的输入将其返回值与1进行比较。

您的编译器警告您这一点不是特别因为scanf返回一个值,而是因为检查scanf的结果很重要。例如,printf的符合标准的实现也将返回一个值(第7.19.6.3.3节),但这对于检查程序的健全性并不关键。

答案 1 :(得分:2)

您将忽略scanf调用的返回值。
这就是编译器警告的内容,并被告知将其视为错误。
请理解,用scanf()可能会犯很多细微的错误,而不在乎成功,这由返回值表示。

要隐藏编译器会通知您的问题,我建议您首先尝试“显而易见”的直接方法

int IreallyWantToIgnoreTheImportantInfo;
/* ... */
IreallyWantToIgnoreTheImportantInfo = scanf("%d",&n);

但是,这只会将问题转移到其他地方,而忽略scanf()返回值的有效原因很可能(或可能是“希望”)变成“变量集,但从未使用过”警告。

在这里真正解决问题的正确方法是使用返回值。 您可以例如进行循环,尝试读取用户输入(给出解释并删除未扫描的尝试),直到返回值指示成功。

这可能会使代码更好,至少更健壮。

如果您真的想忽略而不是忽略包含信息的变量,请尝试

(void) scanf("%d",&n); /* I really really do not care ... */

但是,请按照我的意思认为这完全有用,这不是一个好主意。

答案 2 :(得分:1)

  

有人可以向我解释这是什么问题以及如何纠正此问题吗?

许多C函数将值返回给它们的调用者。 C不需要调用者确认或处理此类返回值,但是通常,忽略返回值会构成程序缺陷。这是因为忽略返回值通常意味着以下情况之一:

  • 调用该函数是为了获取其返回值,因此对该值执行任何操作本身就是错误,或者

  • 该函数主要是由于其副作用而被调用的,但是它的返回值(传达了有关函数成功产生这些副作用的信息)被忽略了。有时,调用者确实并不在乎函数的成功程度,但是通常,忽略返回值意味着程序正在假定完全成功,因此,如果未真正实现,则它将出现故障。

通常,

scanf()的副作用是:从标准输入中读取格式化的数据并将其记录在指定的对象中。它的返回值指示成功处理了多少个给定的输入字段,并且如果在解析任何字段之前遇到流的末尾或I / O错误,则返回值也将通过特殊的返回值来指示。

如果您不验证scanf是否阅读了您希望它执行的所有字段,那么您将不知道它是否为您提供了任何可使用的数据,也无法确定输入的状态。例如,假设您在运行程序时输入“ x”而不是数字。您认为它将做什么?

您似乎正在使用GCC和GLIBC。当忽略某些函数(包括scanf)的返回值时,默认情况下会使用它们来产生警告。这捕获了许多更常见的此类漏洞案例。为避免此类警告,请正确检查返回值。例如,

if (scanf("%d",&n) != 1) {
    fputs("Invalid input -- aborting.\n", stderr);
    exit(1);
}

答案 3 :(得分:0)

发生的情况是,如果不检查scanf返回的值,则会将编译器配置为向您发出警告。

您可以通过多种方式“修复”此问题:

  • 您可以将编译器配置为停止警告您。这通常是个坏主意,但是由于您仍在学习C,因此在此步骤中专注于错误检查可能会适得其反。
  • 您可以将scanf的结果放入变量....中,而不对其进行任何处理。它可能会愚弄编译器。和以前一样,不是一个好主意...
  • 您实际上可以对scanf进行错误检查。自从您学习C以来,这可能会令人困惑,但是最后这将是一个非常好的习惯:每次调用可能失败的函数时,请检查它是否成功。为此,您必须阅读scanf manual:不要尝试全部阅读,在结束之前您可能会头疼。 Juste阅读了“返回值”部分,这是非常重要的。

祝你好运!

答案 4 :(得分:0)

您的编译器警告您的是以下内容:

您正在使用scanf()读取输入(您无法控制)。您告诉scanf()您期望一个整数"%d",并且scanf()应该将转换结果放入&n所提供的变量中。

现在,当您的用户未输入整数而是改为使用"evil message"时,会发生什么?好吧,scanf()无法将其转换为整数。因此,您的变量n将不会初始化。 让程序意识到出了点问题的唯一方法是检查scanf()返回的内容。如果返回的内容表明1转换成功,则一切正常。如果返回其他值,则说明您已在程序中输入了一些垃圾。 (通常,如果发生错误,您可能会希望通过描述性的错误消息来纾困,但具体情况取决于上下文)

处理输入错误的失败是最容易利用的安全漏洞,并且编译器的开发人员都知道这一点。因此,他们认为忽略scanf()的返回值通常是一个非常糟糕的主意,因为这是捕获scanf()输入错误的唯一方法。他们很方便地告诉您有关此的信息。 尝试遵循他们的建议,并确保您确实处理了可能发生的错误,或证明可以安全地忽略这些错误