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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7271939/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:33:42  来源:igfitidea点击:

Warning: ignoring return value of 'scanf', declared with attribute warn_unused_result

c

提问by vipin

#include <stdio.h>

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

I compiled the above C code using ideone.com and the following warning popped up:

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

prog.c: In function ‘main':
prog.c:5: warning: ignoring return value of ‘scanf', declared with attribute warn_unused_result

prog.c:在函数“main”中:
prog.c:5:警告:忽略用属性warn_unused_result声明的“scanf”的返回值

Can someone help me understand this warning?

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

回答by Evan Teran

The writer's of your libc have decided that the return value of scanfshould not be ignored in most cases, so they have given it an attribute telling the compiler to give you a warning.

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

If the return value is truly not needed, then you are fine. However, it is usually best to check it to make sure you actually successfully read what you think you did.

如果真的不需要返回值,那么你很好。但是,通常最好检查它以确保您确实成功阅读了您认为自己所做的事情。

In your case, the code could be written like this to avoid the warning (and some input errors):

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

#include <stdio.h>

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

回答by Alexandre C.

The warning (rightly) indicates that it is a bad idea not to check the return value of scanf. The function scanfhas been explicitly declared (via a gcc function attribute) to trigger this warning if you discard its return value.

警告(正确地)表明不检查 的返回值是一个坏主意scanf。该函数scanf已明确声明(通过gcc 函数属性)以在您丢弃其返回值时触发此警告。

If you really want to forget about this return value, while keeping the compiler (and your conscience) happy, you can cast the return value to void:

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

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

回答by Quigi

I tried your example with gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3. The warning is issued if and only if optimizing, e.g., with option -O2 or -O3. Requesting all warnings (-Wall) doesn't matter. The classic idiom of casting to void has no effect, it does not suppress the warning.

我用 gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3 试过你的例子。当且仅当优化时发出警告,例如,使用选项 -O2 或 -O3。请求所有警告 (-Wall) 并不重要。cast to void 的经典习语没有效果,它不会抑制警告。

I can silence the warning by writing

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

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

this works, but it's a bit obscure for my taste. Empty {} avoids yet another warning -Wempty-body

这有效,但对我来说有点晦涩。Empty {} 避免了另一个警告 -Wempty-body

回答by Waxrat

Do this:

做这个:

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

回答by Dr Beco

After reading all answers and comments on this page I don't see these yet another options to avoid the warning:

阅读此页面上的所有答案和评论后,我没有看到这些避免警告的另一个选项:

When compilingwith gccyou can add to your command line:

编译gcc您可以添加到您的命令行:

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

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

Another optionis to use -O0as "optimization level zero" ignores the warning.

另一种选择是使用-O0“优化级别为零”忽略警告。

Using cast to (void)is simply uselesswhen compiling with gcc

使用 cast to在编译时(void)根本没用gcc

If debugging your code, you can always use assert()as in the example bellow:

如果调试你的代码,你总是可以assert()像下面的例子一样使用:

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

But now, if you turn off assert via #define NDEBUGyou will get a -Wunused-but-set-variable. You can then turn off this second warningby one of two ways:

但是现在,如果你关闭 assert via#define NDEBUG你会得到一个-Wunused-but-set-variable. 然后,您可以通过以下两种方式之一关闭第二个警告

  1. Adding -Wno-unused-but-set-variableto your gcccommand line, or
  2. Declaring the variable with attribute: int u __attribute__((unused));
  1. 添加-Wno-unused-but-set-variable到您的gcc命令行,或
  2. 用属性声明变量: int u __attribute__((unused));

As pointed out in other answer, the second option unfortunately is not very portable, although it seems the best option.

正如其他答案中所指出的,不幸的是,第二个选项不是很便携,尽管它似乎是最好的选择。

At last, the defined MACRObellow can help you if you are sureyou want to ignore the return of a given function, but you are not comfortable turning off the warnings for allunused returns of functions:

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

#define igr(x) {__typeof__(x) __attribute__((unused)) d=(x);} 

double __attribute__ ((warn_unused_result)) fa(void) {return 2.2;}
igr(fa());


See also this answer

另请参阅此答案

回答by Tino

One way to solve this is the IGUR()function as seen below. Extremely ugly, but nevertheless somewhat portable. (For old compilers which do not understand inlinejust #define inline /*nothing*/, as usual.)

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

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

inline void 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 this example, nonblockingly, copies from stdinto stdoutuntil all waiting input was read, returning true(0) if nothing was there, else false(1). (It prevents the 1s delay in something like while read -t1 away; do :; donein bash.)

顺便说一句,这个例子,非阻塞地,从stdin到复制,stdout直到所有等待的输入被读取,true如果没有,则返回(0),否则返回false(1)。(它可以防止在1秒延时的东西像while read -t1 away; do :; donebash)。

Compiles without warning under -Wall(Debian Jessie).

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

Edit: IGUR()needs to be defined without inline, too, such that it becomes available for the linker. Else with cc -O0it might fail. See: https://stackoverflow.com/a/16245669/490291

编辑:也IGUR()需要在没有 的情况下定义inline,以便链接器可以使用它。否则cc -O0可能会失败。参见:https: //stackoverflow.com/a/16245669/490291

Edit2: Newer gccrequire inlineto be before void.

Edit2:较新的gcc需要inlinevoid.

回答by stdcall

scanf, printf is functions that returns value, usually in those kind of functions it's the amount of characters read or written. if an error occurs, you can catch the error also with the return code. A good programming practice will be to look at the return value, however, I never saw someone who looks at the printf return value...

scanf, printf 是返回值的函数,通常在这些函数中,它是读取或写入的字符数。如果发生错误,您也可以使用返回码捕获错误。一个好的编程习惯是查看返回值,但是,我从未见过有人查看 printf 返回值......

If you want the warning to disappear, you can probably change the severity of the compiler.

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

回答by u3618748

Can someone help me understand this warning?

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

No, but here is my contribution to the horror of warning suppression. To actively throw out the return value, elegance dictates wrapping our statement in a comprehensiblelambda function, like this:

不,但这是我对警告抑制的恐怖的贡献。为了主动丢弃返回值,优雅要求将我们的语句包装在一个可理解的lambda 函数中,如下所示:

[&]{ return scanf("%d", &t); }();

My apologies.

我很抱歉。

回答by Jari Vetoniemi

Since functions without arguments are valid in C, you can do the following:

由于没有参数的函数在 C 中有效,您可以执行以下操作:

#include <stdio.h>

static inline void ignore_ret() {}

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

回答by Acton

Actually it depends on what you need, if you just want to disable the warning of compiler, you can just ignore the return value of the function by the force conversion or you can just handle it, the meaning of the scanffunction is the count of user input.

其实这取决于你需要什么,如果你只是想禁用编译器的警告,你可以通过强制转换忽略函数的返回值或者你可以处理它,scanf函数的含义是用户的计数输入。

==== update ====

====更新====

You can use

您可以使用

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

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

to ignore the return value of scanf

忽略返回值 scanf