int fn();
void whatever()
{
(void) fn();
}
Is there any reason for casting an unused return value to void, or am I right in thinking it\'s a c
Also when verifying your code complies to MISTA (or other) standards, automatic tools such as LDRA will not allow you to call a function that has a return type without having it return a value unless you explicitly cast the returned value to (void)
At work we use that to acknowledge that the function has a return value but the developer has asserted that it is safe to ignore it. Since you tagged the question as C++ you should be using static_cast:
static_cast<void>(fn());
As far as the compiler goes casting the return value to void has little meaning.
Cast to void is costless. It is only information for compiler how to treat it.
C++17 [[nodiscard]]
C++17 standardized the "return value ignored business" with an attribute.
Therefore, I hope that compliant implementations will always warn only when nodiscard
is given, and never warn otherwise.
Example:
main.cpp
[[nodiscard]] int f() {
return 1;
}
int main() {
f();
}
compile:
g++ -std=c++17 -ggdb3 -O0 -Wall -Wextra -pedantic -o main.out main.cpp
outcome:
main.cpp: In function ‘int main()’:
main.cpp:6:6: warning: ignoring return value of ‘int f()’, declared with attribute nodiscard [-Wunused-result]
6 | f();
| ~^~
main.cpp:1:19: note: declared here
1 | [[nodiscard]] int f() {
|
The following all avoid the warning:
(void)f();
[[maybe_unused]] int i = f();
I wasn't able to use maybe_unused
directly on the f()
call:
[[maybe_unused]] f();
gives:
main.cpp: In function ‘int main()’:
main.cpp:6:5: warning: attributes at the beginning of statement are ignored [-Wattributes]
6 | [[maybe_unused]] f();
| ^~~~~~~~~~~~~~~~
The (void)
cast working does not appear to be mandatory but is "encouraged" in the standard: How can I intentionally discard a [[nodiscard]] return value?
Also as seen from the warning message, one "solution" to the warning is to add -Wno-unused-result
:
g++ -std=c++17 -ggdb3 -O0 -Wall -Wextra -pedantic -Wno-unused-result -o main.out main.cpp
although I wouldn't of course recommend ignoring warnings globally like this.
C++20 also allows you to add a reason to the nodiscard
as in [[nodiscard("reason")]]
as mentioned at: https://en.cppreference.com/w/cpp/language/attributes/nodiscard
GCC warn_unused_result
attribute
Before the standardization of [[nodiscard]]
, and for C before they finally decide to standardize attributes, GCC implemented the exact same functionality with the warn_unused_result
:
int f() __attribute__ ((warn_unused_result));
int f() {
return 1;
}
int main() {
f();
}
which gives:
main.cpp: In function ‘int main()’:
main.cpp:8:6: warning: ignoring return value of ‘int f()’, declared with attribute warn_unused_result [-Wunused-result]
8 | f();
| ~^~
It should be noted then that since ANSI C does not have a standard for this, ANSI C does not specify which C standard library functions have the attribute or not and therefore implementations have made their own decisions on what should or not be marked with warn_unuesd_result
, which is why in general you would have to use the (void)
cast to ignore returns of any calls to standard library functions to fully avoid warnings in any implementation.
Tested in GCC 9.2.1, Ubuntu 19.10.
Since c++17 we have the [[maybe_unused]]
attribute which can be used instead of the void
cast.
Casting to void
is used to suppress compiler warnings for unused variables and unsaved return values or expressions.
The Standard(2003) says in §5.2.9/4 says,
Any expression can be explicitly converted to type “cv void.” The expression value is discarded.
So you can write :
//suppressing unused variable warnings
static_cast<void>(unusedVar);
static_cast<const void>(unusedVar);
static_cast<volatile void>(unusedVar);
//suppressing return value warnings
static_cast<void>(fn());
static_cast<const void>(fn());
static_cast<volatile void>(fn());
//suppressing unsaved expressions
static_cast<void>(a + b * 10);
static_cast<const void>( x &&y || z);
static_cast<volatile void>( m | n + fn());
All forms are valid. I usually make it shorter as:
//suppressing expressions
(void)(unusedVar);
(void)(fn());
(void)(x &&y || z);
Its also okay.