警告:忽略使用属性warn_unused_result声明的“scanf”的返回值

#include <stdio.h> int main() { int t; scanf("%d", &t); printf("%d", t); return 0; } 

我使用ideone.com编译了上面的C代码,popup如下警告:

prog.c:在函数'main'中:
prog.c:5:warning:忽略'scanf'的返回值,用属性warn_unused_result声明

有人能帮我理解这个警告吗?

libc的作者已经决定在大多数情况下scanf的返回值不应该被忽略,所以他们给了它一个属性,告诉编译器给你一个警告。

如果返回值真的不需要,那么你很好。 但是,通常最好检查一下,以确保你实际上成功地阅读了你的想法。

在你的情况下,代码可以这样写,以避免警告(和一些input错误):

 #include <stdio.h> int main() { int t; if (scanf("%d", &t) == 1) { printf("%d", t); } else { printf("Failed to read integer.\n"); } return 0; } 

警告(正确)表明不检查scanf的返回值是一个坏主意。 如果放弃其返回值,函数scanf已经显式声明(通过gcc函数属性 )来触发此警告。

如果你真的想忘记这个返回值,同时保持编译器(和你的良心)的快乐,你可以将返回值转换为void:

 (void)scanf("%d",&t); 

我试着用gcc(Ubuntu 4.4.3-4ubuntu5.1)4.4.3的例子。 当且仅当使用选项-O2或-O3进行优化时才会发出警告。 请求所有警告(-Wall)无关紧要。 铸造无效的经典成语没有效果 ,它不会压制警告。

我可以通过写作来消除警告

 if(scanf("%d",&t)){}; 

这有用,但对我的口味有点模糊。 空{}避免了另一个警告 – 空体

做这个:

 int main() { int t; int unused __attribute__((unused)); unused = scanf("%d",&t); printf("%d",t); return 0; } 

解决这个问题的一个方法是IGUR()函数,如下所示。 非常丑陋,但有点便携。 (对于不懂inline老编译器,像往常一样,只是#define inline /*nothing*/ )。

 #include <stdio.h> #include <unistd.h> #include <fcntl.h> void inline IGUR() {} /* Ignore GCC Unused Result */ void IGUR(); /* see https://stackoverflow.com/a/16245669/490291 */ int main(int argc, char **argv) { char buf[10*BUFSIZ]; int got, fl, have; fl = fcntl(0, F_GETFL); fcntl(0, F_SETFL, fl|O_NONBLOCK); have = 0; while ((got=read(0, buf, sizeof buf))>0) { IGUR(write(1, buf, got)); have = 1; } fcntl(0, F_SETFL, fl); return have; } 

顺便说一下,这个例子非阻塞地从stdin拷贝到stdout直到所有等待的input被读取,如果什么都没有,则返回true (0),否则返回false (1)。 (它可以防止while read -t1 away; do :; done类似延迟while read -t1 away; do :; donebash while read -t1 away; do :; done )。

-Wall (Debian Jessie)下编译没有警告。

编辑: IGUR()需要在没有inline情况下进行定义,以便链接器可用。 否则,可能会失败。 请参阅: https : //stackoverflow.com/a/16245669/490291

scanf,printf是返回值的函数,通常在这些types的函数中是读取或写入的字符数量。 如果发生错误,则可以使用返回码捕获错误。 一个好的编程习惯是看看返回值,但是,我从来没有看到有人看着printf返回值…

如果您希望警告消失,则可以更改编译器的严重性。

在阅读了本页面上的所有答案和评论之后,我没有看到这些避免警告的另一种select:

当用gcc 编译时 ,你可以添加到你的命令行中:

gcc -Wall -Wextra -Wno-unused-result proc.c -o prog.x

另一个select是使用-O0作为“优化级别零”忽略警告。

当使用gcc编译时,使用cast (void)无用的

如果debugging你的代码,你可以使用assert() ,如下面的例子所示:

 u = scanf("%d", &t); assert(u == 1); 

但是现在,如果你通过#define NDEBUGclosuresassert,你会得到一个-Wunused-but-set-variable 。 然后可以通过以下两种方法之一closures第二个警告

  1. -Wno-unused-but-set-variable到您的gcc命令行或
  2. 用属性声明variables: int u __attribute__((unused));

正如在其他答案中指出的,不幸的是,第二种select不是很便携,尽pipe它似乎是最好的select。

最后,如果您确定要忽略给定函数的返回,则定义的MACRO波纹pipe可以为您提供帮助,但对于所有未使用的函数返回,closures警告并不好:

 #define igr(x) {__typeof__(x) __attribute__((unused)) d=(x);} double __attribute__ ((warn_unused_result)) fa(void) {return 2.2;} igr(fa()); 

另请参阅此答案

您可以使用

(void) scanf("%d",&t);

忽略scanf的返回值