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上在家尝试过。
-
你的问题是什么?
-
显然-Wunused-result是小故障,并不总是有效。 可能与优化有关。 我无法复制它,因此我将其视为GCC错误。
忽略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;
} |
-
哦,好吧,我的Uni刚决定调整gcc中的设置,这样它就不会弹出警告了吗?
-
不是你的大学。 决定了它,但这是他们提供给您的编译器选择的结果。
-
但是,检查是否仍然无法从读取错误中恢复的意义何在?
-
通过检查读取错误,您可以停止处理并中止程序,而不是处理垃圾并产生垃圾。
这告诉scanf读取一个十进制数字字符序列(可能带有前缀负号),直到第一个非十进制字符,然后将该序列转换为一个int值,然后将该值存储到example中。
如果用户输入的内容完全不是小数,或者stdin已关闭怎么办? scanf调用将失败,并使用相应的返回值指示这种失败...但是example的值在这种情况下会是什么?
您需要检查返回值,以避免在包含垃圾的情况下使用example。如果您尝试使用该变量,则程序的行为可能不稳定。这可能包括段错误。
您的编译器有权拒绝编译此代码,因为使用未初始化的(或不确定的)变量是未定义的行为。
总而言之,始终检查返回值完全符合您的最大利益,因为:
-
正如您所注意到的,某些编译器可能会拒绝编译没有这种检查的代码。
-
那些确实可以编译代码的程序将使您的程序行为异常,当用户输入垃圾时使用垃圾,或者在某些情况下,由于使用陷阱表示而可能出现段错误。
您没有收到错误,编译器非常友好,可以向您发出警告。正确!输入错误时,example将具有随机值。
始终检查scanf的返回值是否与您要读取的参数数量匹配。
-
啊,我明白了。 因此,例如,如果我有("%d%d",&one和&two),我应该确保有两个参数?
-
@BrandonDuong:不传递参数(格式字符串期望的数字和类型已经是不确定的行为。您还应该遵循编译器的警告并检查是否已设置所有参数。请阅读C书和手册页 如果仍不确定,则为scanf!