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 funct
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.
(void)
no longer works.{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.)
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==((int)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.
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
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...
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);