#include <stdio.h>
int main() {
int t;
scanf("%d", &t);
printf("%d", t);
return 0;
}
我使用ideone.com编译了上面的C代码,并弹出以下警告:
prog.c:在函数'main'中:
声明的'scanf'
prog.c:5:警告:忽略返回值 使用属性warn_unused_result
有人可以帮我理解这个警告吗?
答案 0 :(得分:60)
你的libc的作者已经决定在大多数情况下不应该忽略scanf
的返回值,所以他们给它一个属性告诉编译器给你一个警告。
如果确实不需要返回值,那么你没事。但是,通常最好检查一下,以确保您真正成功地阅读了您认为自己所做的事情。
在您的情况下,代码可以这样写,以避免警告(以及一些输入错误):
#include <stdio.h>
int main() {
int t;
if (scanf("%d", &t) == 1) {
printf("%d", t);
} else {
printf("Failed to read integer.\n");
}
return 0;
}
答案 1 :(得分:16)
警告(正确)表示不检查scanf
的返回值是个坏主意。如果您丢弃其返回值,则已显式声明函数scanf
(通过 gcc函数属性)来触发此警告。
如果你真的想忘记这个返回值,同时保持编译器(和你的良心)满意,你可以将返回值转换为void:
(void)scanf("%d",&t);
答案 2 :(得分:9)
我用gcc(Ubuntu 4.4.3-4ubuntu5.1)4.4.3尝试了你的例子。 当且仅当优化时,例如使用选项-O2或-O3发出警告。 请求所有警告(-Wall)并不重要。 铸造为无效的经典成语没有效果,它不会抑制警告。
我可以通过写
来消除警告if(scanf("%d",&t)){};
这是有效的,但对我的口味来说有点模糊。 Empty {}避免了另一个警告-Wempty-body
答案 3 :(得分:3)
这样做:
int main() {
int t;
int unused __attribute__((unused));
unused = scanf("%d",&t);
printf("%d",t);
return 0;
}
答案 4 :(得分:3)
解决此问题的一种方法是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;
}
BTW此示例非阻塞地从stdin
复制到stdout
,直到读取所有等待输入,如果没有,则返回true
(0),否则false
( 1)。 (它可以阻止while read -t1 away; do :; done
中bash
之类的1秒延迟。)
在-Wall
(Debian Jessie)下编译时没有任何警告。
编辑:IGUR()
也需要在没有inline
的情况下定义,以便链接器可用。否则cc -O0
可能会失败。请参阅:https://stackoverflow.com/a/16245669/490291
答案 5 :(得分:1)
scanf,printf是返回值的函数,通常在那些函数中,它是读取或写入的字符数。如果发生错误,您也可以使用返回码捕获错误。 一个好的编程实践将是查看返回值,但是,我从未见过有人查看printf返回值......
如果您希望警告消失,您可以更改编译器的严重性。
答案 6 :(得分:1)
在阅读本页面上的所有答案和评论之后,我没有看到这些另外的选项来避免警告:
使用gcc
编译时,您可以添加到命令行:
gcc -Wall -Wextra -Wno-unused-result proc.c -o prog.x
另一个选项是使用-O0
作为“优化级别零”忽略警告。
在使用(void)
进行编译时,使用强制转换为gcc
只是无用
如果要调试代码,您可以随时使用 assert()
,如下例所示:
u = scanf("%d", &t);
assert(u == 1);
但现在,如果您通过#define NDEBUG
关闭断言,则会获得-Wunused-but-set-variable
。然后,您可以通过以下两种方式之一关闭此第二次警告:
-Wno-unused-but-set-variable
添加到gcc
命令行,或int u __attribute__((unused));
正如其他答案所指出的,遗憾的是第二种选择并不是很便携,虽然它似乎是最好的选择。
最后,如果您确定要忽略给定功能的返回,定义的 MACRO 可以帮助您,但是您不方便关闭警告所有未使用的函数返回:
#define igr(x) {__typeof__(x) __attribute__((unused)) d=(x);}
double __attribute__ ((warn_unused_result)) fa(void) {return 2.2;}
igr(fa());
答案 7 :(得分:1)
有人可以帮助我理解此警告吗?
否,但这是我对警告抑制的恐惧做出的贡献。为了积极抛出返回值,优雅要求将我们的语句包装在可理解的 lambda函数中,如下所示:
[&]{ return scanf("%d", &t); }();
我很抱歉。
答案 8 :(得分:0)
由于不带参数的函数在C语言中有效,因此您可以执行以下操作:
#include <stdio.h>
static inline void ignore_ret() {}
int main() {
int t;
ignore_ret(scanf("%d", &t));
return 0;
}
答案 9 :(得分:-1)
实际上它取决于你需要什么,如果你只想禁用编译器的警告,你可以通过强制转换忽略函数的返回值,或者你可以只处理它,{{1的含义function是用户输入的计数。
====更新====
您可以使用
scanf
忽略(void) scanf("%d",&t);