51

Lately, I started using lint for static code analysis. One of the warning I get sometimes is regarding this issue. Let's say for instance that I've got the following function:

uint32_t foo( void );

And let's say that I delibertly ignore the return value of the function. To make the warning dissapear, one can write

(void) foo();

My question is, what is the "proper" way to write code like this, should I continue as I always did, since the compiler doesn't complain about it, or should I use the void for clarity, so other code maintainer will know that I delibertly ignored the return value.

When I look at the code like this ( with the void ), it looks pretty strange to me...

stdcall
  • 27,613
  • 18
  • 81
  • 125
  • 2
    Why are you deliberately ignoring the return value? – bpeikes Aug 09 '12 at 17:17
  • 22
    There are situations where return value doesnt matter, for instance, in embedded, if a printf for logging fails, You can't really do anything... Try to write to the user that the printf doesn't work ? :) – stdcall Aug 09 '12 at 17:19
  • 1
    You can usually inhibit reporting of error messages for a named function. It depends on which Lint you are using, but in PC Lint I have something like: '-ecall(534,printf)' which stops it reporting unused return (534) for calls to printf. Most other Lints have some similar mechanism. – Andy Krouwel Nov 02 '16 at 11:56
  • @stdcall Have a designated LED on the product for "printf failed". – Daniel Chin Aug 18 '23 at 11:06

10 Answers10

78

The common way is to just call foo(); without casting into (void).

He who has never ignored printf()'s return value, cast the first stone.

mouviciel
  • 66,855
  • 13
  • 106
  • 140
  • 8
    +1 to the only answer out of 4 that understands the question. Not sure why everyone else is missing the point. – Egor Aug 09 '12 at 17:28
  • 1
    Worth noting: Windows has `UNREFERENCED_PARAMETER` for unused arguments; you could make a similar macro for other expressions. – user541686 Aug 09 '12 at 17:28
  • 9
    I think I personally went the longest time before actually realizing printf returned a value xD. – Dennis Meng Aug 09 '12 at 17:32
  • 3
    Just doing this doesn't work. Look at the answer by @dfsmith – m4l490n Dec 15 '16 at 16:41
  • Any code maintainer that cannot deduce that the return value is ignored from the lack of an assignment operator probably should not me maintaining code. If the program is being "developed" it might be an oversight. If it's in maintenance, then it's reasonable to presume it was a deliberate choice. – Chindraba Aug 27 '18 at 19:31
39

I personally like the "unused" warnings, but on occasion there are instances where I have to ignore them (e.g., the write() to user, or fscanf(...,"%*s\n") or strtol() where the return value is unimportant and I just want the side effect of [maybe] moving the file pointer along.)

With gcc 4.6, it's getting quite tricky.

  • Casting to (void) no longer works.
  • Re-writing functions (especially variadic) is tedious and clumsy.
  • {ssize_t ignore; ignore=write(...);} throws up another warning (assigned-not-used).
  • write(...)+1 throws up yet another warning (computed-value-not-used).

The only good (if ugly) way to suppress these is to convert the return value into something that the compiler agrees that you can ignore.

E.g., (void)(write(...)+1).

This is apparently progress. (And +0 does not work, BTW.)

Abdul Rahman
  • 2,097
  • 4
  • 28
  • 36
dfsmith
  • 391
  • 3
  • 2
  • Thank you very much for your trick! While you don't answer the original question (how to avoid that warning with "lint"), you answer another very legitimate question (how to avoid that warning with gcc). – Kai Petzke Mar 16 '14 at 10:53
  • Ignoring write() return value is actually not such a good idea. I've had bugs that I would have found much faster if I had not ignored it. – kec May 17 '14 at 22:12
  • 3
    `if( write(...) );` should work as well. Don't forget the tailing semicolon `;`. – con-f-use Mar 27 '15 at 12:13
  • similar to con-f-use I have just adopted a simlar tendency: but I put a debug output in. that's easy in Qt and a sane thing to do. If I'm ever running the code on a desktop I get sane warnings of things going awry but nothing happens on release code. – LovesTha Apr 22 '16 at 06:33
  • 1
    This should be the correct answer. Just casting to (void) doesn't work – m4l490n Dec 15 '16 at 16:40
  • 2
    `(void)!foo(); /*works with gcc4.6+ */` best to place in a macro or inline function. Better to use a tool that supports a **can not ignore**. Some returns are informational and other are critical. – artless noise Apr 30 '20 at 19:27
24

One way to do this with Clang and GCC compilers is with a pragma:

    /* ... */

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result" 

    foo(); /* this specific unused-result warning gets ignored during compilation */

#pragma GCC diagnostic pop 

    /* ... */

The push-pop combination wraps the ignored directive so that warnings can be triggered elsewhere in your code. It should be easier for anyone reading your source code down the road to see what this code block does.

Alex Reynolds
  • 95,983
  • 54
  • 240
  • 345
13

One slightly more "beautiful" way of indicating unused results would be this:

/**
 * Wrapping your function call with ignore_result makes it more clear to
 * readers, compilers and linters that you are, in fact, ignoring the
 * function's return value on purpose.
 */
static inline void ignore_result(long long int unused_result) {
    (void) unused_result;
}

...

ignore_result(foo());

With C++, this may be extended to:

template<typename T>
inline void ignore_result(const T & /* unused result */) {}
mic_e
  • 5,594
  • 4
  • 34
  • 49
  • 3
    This is my preferred solution. I must say, however, the C example that works properly would be: `static inline void ignore_result(ssize_t unused) { (void)unused; }` since you cannot omit the parameter identifier in C as you can in C++. Also, with gcc if you don't add `static` it will generate a linker error if you disable optimizations. – Watcom Jul 11 '16 at 00:22
  • 2
    Thanks for noticing; I have fixed my answer accordingly. – mic_e Jul 11 '16 at 11:45
  • Of the assorted answers given, this is also my preferred solution in 2019. Thanks! – Xunnamius May 13 '19 at 22:39
  • updated the C++ solution to replace the by-value parameter by a const reference parameter which is guaranteed to be free of side effects even in weird edge cases. – mic_e Feb 24 '20 at 17:04
9

For a static code checker to be useful, it should report also the ignored return values, which can lead very often to difficult to track errors - or missing error handling.

So you should keep the (void) or deactivate the check for printf. Now you have several options for doing it in a readable manner. I use to wrap the function inside a new function like for example

void printf_unchecked(const char* format, ...)

where the not so nice cast takes place. Perhaps it's more practical to do it using a preprocessor macro in this case because of the varargs...

jdehaan
  • 19,700
  • 6
  • 57
  • 97
  • 2
    +1, even though I personally prefer the plain `(void)` cast. Thank you for understanding the question and offering a different approach – stefan Aug 09 '12 at 17:31
  • 2
    I like the idea of using a preprocessor macro. Perhaps something like: #define UNCHECKED_RV(function_call) (void)function_call The benefit of this solution or the function_unchecked() wrapper is that it makes it very clear that you are purposely ignoring the return value. Casting to void isn't nearly as clear. – bpeikes Aug 10 '12 at 14:46
8

I like to compile my codes with the flags:

$gcc prog1.c -o prog1.x -Wall -Wextra -ansi -pedantic-errors -g -O0 -DDEBUG=1

And to avoid -Wunused-result I don't like the idea of adding another flag: -Wno-unused-result (if you do, thats one solution).

I used to cast to (void) for some functions (not printf or other famous, as the compilers dont warn about them, just the strange ones). Now casting to (void) does not work anymore (GCC 4.7.2)

Funny splint advises:

Result returned by function call is not used. If this is intended,
can cast result to (void) to eliminate message. (Use -retvalother to
inhibit warning)

But this is not a solution anymore. Splint needs an update regarding this issue.

So, to get rid of the warning in a very compatible way, here is a good MACRO:

/** Turn off -Wunused-result for a specific function call */
#define igr(M) if(1==((long)M)){;}

And call it like this:

igr(PL_get_chars(t, &s, CVT_VARIABLE));

Its a clean look, and any compiler will eliminate the code. Bellow a picture of my preferred editor vi: left window, no igr(); middle window, using igr(); right window, source.

enter image description here

You can see, its exactly the same, a completely innocuous code that let C do what gcc won't let: ignore the return code.

The comparison 1==... is necessary only to avoid splint warning that this conditional is no BOOL. GCC couldn't care less. Depending on the function, you might get a cast warning. I did a test ignoring a double with this MACRO and it was good, but somehow I'm not fully convinced. Specially if the function returns a pointer or something more complex.

In this case you will also need:

#define pigr(M) if(NULL==((void *)M)){;}

Last thing: the {;} is necessary because of the -Wempty-body warning (suggest braces around empty body in an ‘if’ statement).

And (now the last thing) the ; after the function call is not (strictly) necessary, but its good practice. Makes your code lines more homogeneous, all of them ending in a ;. (It's translated as a NOP mnemonic, and after optimization, disappear).


Running the compiler gives no warning or errors. Runing splint gives:

$ splint ./teste.c -I/usr/lib/swi-prolog/include/ -strict-lib
Splint 3.1.2 --- 20 Feb 2009

Finished checking --- no warnings

See also this answer

DrBeco
  • 11,237
  • 9
  • 59
  • 76
  • 1
    BTW, better if you know what you are doing and if possible, check the return value. Regarding this example I gave, with SWI-Prolog, my solution is to edit SWI-Prolog.h and allow the redefinition of WUNUSED `__attribute__ ((warn_unused_result))` with a GCC key `-DWUNUSED=""` – DrBeco Jun 23 '15 at 05:43
  • Good to mention `-Wno-unused-result` – qwr Dec 25 '22 at 17:49
3

gnulib has this: http://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/ignore-value.h

/* Normally casting an expression to void discards its value, but GCC
   versions 3.4 and newer have __attribute__ ((__warn_unused_result__))
   which may cause unwanted diagnostics in that case.  Use __typeof__
   and __extension__ to work around the problem, if the workaround is
   known to be needed.  */
#if 3 < __GNUC__ + (4 <= __GNUC_MINOR__)
# define ignore_value(x) \
    (__extension__ ({ __typeof__ (x) __x = (x); (void) __x; }))
#else
# define ignore_value(x) ((void) (x))
#endif
Eric Blake
  • 51
  • 1
1

Usually there are not too many functions the value of which you want to ignore. Splint, for example, allows to add a special comment that would let it know, that a return value of a specific function might be ignored. Unfortunately, this in effect disables all 'ignored returned value' warning related to that particular function.

Here is an example of Splint-clean program:

#include <stdio.h>

FILE /*@alt void@*/ *fopen(const char *path, const char *mode);

static int /*@alt void@*/ test(void)
{
   printf( "test called\n" );

   fopen( "test", "a" );

   return 0;
}

int main(void)
{  
   test();

   return 0;
}

The unpleasant part is that you need to add an additional prototype to a system function with a comment somewhere.

Btw,by default Splint doesn't complain about the return value of printf and of some other libc functions being unused. However, a stricter mode can be activated.

LINT allows something similar, but I have never used it. Here is what a documentation says.

LINT lets you mark functions with optional return values by using a directive similar to the #directives of the C preprocessor.

#pragma optresult

can be placed immediately before the definition of a function that returns an optional result. LINT then recognizes that this function returns a result that can be ignored; LINT does not give error messages if the result is ignored.

Maksim Skurydzin
  • 10,301
  • 8
  • 40
  • 53
1

Other solution would be to actually use a value. Then you could remove the unused variable warning with a macro.

#define _unused(x) ((void)(x))

Then in your example, you'd have:

val = foo();
_unused(val); 
user9869932
  • 6,571
  • 3
  • 55
  • 49
-1

It is entirely legal and acceptable to write code that ignores the return value in some cases. The program below has very little reason to check the return value of printf().

int main(void) {
  printf("Hello world\n");
  return 0;
}
Variable Length Coder
  • 7,958
  • 2
  • 25
  • 29