警告:忽略使用属性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 :; done
在bash
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 NDEBUG
closuresassert,你会得到一个-Wunused-but-set-variable
。 然后可以通过以下两种方法之一closures第二个警告 :
- 将
-Wno-unused-but-set-variable
到您的gcc
命令行或 - 用属性声明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
的返回值