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

时间:2011-09-01 14:39:27

标签: c

#include <stdio.h>

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

我使用ideone.com编译了上面的C代码,并弹出以下警告:

  

prog.c:在函数'main'中:
  prog.c:5:警告:忽略返回值   使用属性warn_unused_result

声明的'scanf'

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

10 个答案:

答案 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 :; donebash之类的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。然后,您可以通过以下两种方式之一关闭此第二次警告

  1. -Wno-unused-but-set-variable 添加到gcc命令行,或
  2. 使用属性 int u __attribute__((unused));
  3. 声明变量

    正如其他答案所指出的,遗憾的是第二种选择并不是很便携,虽然它似乎是最好的选择。

    最后,如果您确定要忽略给定功能的返回,定义的 MACRO 可以帮助您,但是您不方便关闭警告所有未使用的函数返回:

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

    另见this answer

答案 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);

的返回值