关于C#:忽略scanf的返回值

Ignoring return value of scanf

我有一个问题,其中使用Werror参数的gcc出现错误"忽略scanf的返回值"。 现在,我检查了论坛,并做了一些工作,例如将它放在if语句中,这似乎很好用,但事实是,如果我在大学编译它,则不会收到错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>

#define EXAMPLE1 5

int main (int argc, char* argv[]) {
int example;


   scanf ("%d", &example);
   if (example <= EXAMPLE1) {
       printf ("Woohoo\
"
);
   }   else {
       printf ("Oohoow\
"
);

   }

   return EXIT_SUCCESS;

}

因此,例如,在我的uni上使用gcc -Wall -Werror -O -o namehere namehere.c可以很好地编译此代码,但是如果我要在家中使用它,则会出现上述错误。 我的大学正在使用gcc 4.9.2。 我在gcc 4.8.4、4.8.5、4.9.3上在家尝试过。


忽略scanf()的返回值不是很好,因为这意味着您没有检查输入中是否可能存在错误。尽管某些编译器或设置未对此给出警告,但您不应忽略scanf()的返回值。

试试这个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <stdlib.h>

#define EXAMPLE1 5

int main (int argc, char* argv[]) {

   int example;

   if (scanf ("%d", &example) != 1) {
       printf ("Read error\
"
);
   }
   else if (example <= EXAMPLE1) {
       printf ("Woohoo\
"
);
   }   else {
       printf ("Oohoow\
"
);

   }

   return 0;

}


1
scanf ("%d", &example);

这告诉scanf读取一个十进制数字字符序列(可能带有前缀负号),直到第一个非十进制字符,然后将该序列转换为一个int值,然后将该值存储到example中。

如果用户输入的内容完全不是小数,或者stdin已关闭怎么办? scanf调用将失败,并使用相应的返回值指示这种失败...但是example的值在这种情况下会是什么?

您需要检查返回值,以避免在包含垃圾的情况下使用example。如果您尝试使用该变量,则程序的行为可能不稳定。这可能包括段错误。

您的编译器有权拒绝编译此代码,因为使用未初始化的(或不确定的)变量是未定义的行为。

总而言之,始终检查返回值完全符合您的最大利益,因为:

  • 正如您所注意到的,某些编译器可能会拒绝编译没有这种检查的代码。
  • 那些确实可以编译代码的程序将使您的程序行为异常,当用户输入垃圾时使用垃圾,或者在某些情况下,由于使用陷阱表示而可能出现段错误。

您没有收到错误,编译器非常友好,可以向您发出警告。正确!输入错误时,example将具有随机值。

始终检查scanf的返回值是否与您要读取的参数数量匹配。