What exactly does `(void)SomeBaseClass;` do? [duplicate] - c++

This question already has answers here:
Why cast unused return values to void?
(10 answers)
Closed 1 year ago.
An often used statement like (void)x; allows to suppress warnings about unused variable x. But if I try compiling the following, I get some results I don't quite understand:
int main()
{
int x;
(short)x;
(void)x;
(int)x;
}
Compiling this with g++, I get the following warnings:
$ g++ test.cpp -Wall -Wextra -o test
test.cpp: In function ‘int main()’:
test.cpp:4:13: warning: statement has no effect [-Wunused-value]
(short)x;
^
test.cpp:6:11: warning: statement has no effect [-Wunused-value]
(int)x;
^
So I conclude that casting to void is very different from casting to any other types, be the target type the same as decltype(x) or something different. My guess at possible explanations is:
It is just a convention that (void)x; but not the other casts will suppress warnings. All the statements equally don't have any effect.
This difference is somehow related to the fact that void x; isn't a valid statement while short x; is.
Which of these if any is more correct? If none, then how can the difference in compiler warnings be explained?

Casting to void is used to suppress compiler warnings. The Standard says in §5.2.9/4 says,
Any expression can be explicitly converted to type “cv void.” The
expression value is discarded.

This statement:
(void)x;
Says "Ignore the value of x." There is no such type as void - it is the absence of a type. So it's very different from this:
(int)x;
Which says "Treat x as if it were an integer." When the resulting integer is ignored, you get a warning (if it's enabled).
When you ignore something which is nothing, it is not considered a problem by GCC--and with good reason, since casting to void is an idiomatic way to ignore a variable explicitly in C and C++.

The standard does not mandate generating a warning ("diagnostic" in standardese) for unused local variables or function parameters. Likewise, it does not mandate how such a warning might be suppressed. Casting a variable expression to void to suppress this warning has become an idiom in the C and later C++ community instead because the result cannot be used in any way (other than e.g. (int)x), so it's unlikely that the corresponding code is just missing. E.g.:
(int)x; // maybe you meant f((int)x);
(void)x; // cannot have intended f((void)x);
(void)x; // but remote possibility: f((void*)x);
Personally, I find this convention too obscure still, which is why I prefer to use a function template:
template<typename T>
inline void ignore(const T&) {} // e.g. ignore(x);
The idiomatic way to ignore function parameters is, however, to omit their name (as seen above). A frequent use I have for this function is when I need to be able to name a function parameter in conditionally compiled code such as an assert. I find e.g. the following more legible than the use of #ifdef NDEBUG:
void rate(bool fantastic)
{
assert(fantastic);
ignore(fantastic);
}

Possible use:
auto it = list_.before_begin();
for (auto& entry : list_)
{
(void)entry; //suppress warning
++it;
}
Now the iterator 'it' points to the last element

Related

What does (void)char_ptr;? [duplicate]

This question already has answers here:
Why cast unused return values to void?
(10 answers)
Closed 1 year ago.
An often used statement like (void)x; allows to suppress warnings about unused variable x. But if I try compiling the following, I get some results I don't quite understand:
int main()
{
int x;
(short)x;
(void)x;
(int)x;
}
Compiling this with g++, I get the following warnings:
$ g++ test.cpp -Wall -Wextra -o test
test.cpp: In function ‘int main()’:
test.cpp:4:13: warning: statement has no effect [-Wunused-value]
(short)x;
^
test.cpp:6:11: warning: statement has no effect [-Wunused-value]
(int)x;
^
So I conclude that casting to void is very different from casting to any other types, be the target type the same as decltype(x) or something different. My guess at possible explanations is:
It is just a convention that (void)x; but not the other casts will suppress warnings. All the statements equally don't have any effect.
This difference is somehow related to the fact that void x; isn't a valid statement while short x; is.
Which of these if any is more correct? If none, then how can the difference in compiler warnings be explained?
Casting to void is used to suppress compiler warnings. The Standard says in §5.2.9/4 says,
Any expression can be explicitly converted to type “cv void.” The
expression value is discarded.
This statement:
(void)x;
Says "Ignore the value of x." There is no such type as void - it is the absence of a type. So it's very different from this:
(int)x;
Which says "Treat x as if it were an integer." When the resulting integer is ignored, you get a warning (if it's enabled).
When you ignore something which is nothing, it is not considered a problem by GCC--and with good reason, since casting to void is an idiomatic way to ignore a variable explicitly in C and C++.
The standard does not mandate generating a warning ("diagnostic" in standardese) for unused local variables or function parameters. Likewise, it does not mandate how such a warning might be suppressed. Casting a variable expression to void to suppress this warning has become an idiom in the C and later C++ community instead because the result cannot be used in any way (other than e.g. (int)x), so it's unlikely that the corresponding code is just missing. E.g.:
(int)x; // maybe you meant f((int)x);
(void)x; // cannot have intended f((void)x);
(void)x; // but remote possibility: f((void*)x);
Personally, I find this convention too obscure still, which is why I prefer to use a function template:
template<typename T>
inline void ignore(const T&) {} // e.g. ignore(x);
The idiomatic way to ignore function parameters is, however, to omit their name (as seen above). A frequent use I have for this function is when I need to be able to name a function parameter in conditionally compiled code such as an assert. I find e.g. the following more legible than the use of #ifdef NDEBUG:
void rate(bool fantastic)
{
assert(fantastic);
ignore(fantastic);
}
Possible use:
auto it = list_.before_begin();
for (auto& entry : list_)
{
(void)entry; //suppress warning
++it;
}
Now the iterator 'it' points to the last element

What does casting to `void` really do? [duplicate]

This question already has answers here:
Why cast unused return values to void?
(10 answers)
Closed 1 year ago.
An often used statement like (void)x; allows to suppress warnings about unused variable x. But if I try compiling the following, I get some results I don't quite understand:
int main()
{
int x;
(short)x;
(void)x;
(int)x;
}
Compiling this with g++, I get the following warnings:
$ g++ test.cpp -Wall -Wextra -o test
test.cpp: In function ‘int main()’:
test.cpp:4:13: warning: statement has no effect [-Wunused-value]
(short)x;
^
test.cpp:6:11: warning: statement has no effect [-Wunused-value]
(int)x;
^
So I conclude that casting to void is very different from casting to any other types, be the target type the same as decltype(x) or something different. My guess at possible explanations is:
It is just a convention that (void)x; but not the other casts will suppress warnings. All the statements equally don't have any effect.
This difference is somehow related to the fact that void x; isn't a valid statement while short x; is.
Which of these if any is more correct? If none, then how can the difference in compiler warnings be explained?
Casting to void is used to suppress compiler warnings. The Standard says in §5.2.9/4 says,
Any expression can be explicitly converted to type “cv void.” The
expression value is discarded.
This statement:
(void)x;
Says "Ignore the value of x." There is no such type as void - it is the absence of a type. So it's very different from this:
(int)x;
Which says "Treat x as if it were an integer." When the resulting integer is ignored, you get a warning (if it's enabled).
When you ignore something which is nothing, it is not considered a problem by GCC--and with good reason, since casting to void is an idiomatic way to ignore a variable explicitly in C and C++.
The standard does not mandate generating a warning ("diagnostic" in standardese) for unused local variables or function parameters. Likewise, it does not mandate how such a warning might be suppressed. Casting a variable expression to void to suppress this warning has become an idiom in the C and later C++ community instead because the result cannot be used in any way (other than e.g. (int)x), so it's unlikely that the corresponding code is just missing. E.g.:
(int)x; // maybe you meant f((int)x);
(void)x; // cannot have intended f((void)x);
(void)x; // but remote possibility: f((void*)x);
Personally, I find this convention too obscure still, which is why I prefer to use a function template:
template<typename T>
inline void ignore(const T&) {} // e.g. ignore(x);
The idiomatic way to ignore function parameters is, however, to omit their name (as seen above). A frequent use I have for this function is when I need to be able to name a function parameter in conditionally compiled code such as an assert. I find e.g. the following more legible than the use of #ifdef NDEBUG:
void rate(bool fantastic)
{
assert(fantastic);
ignore(fantastic);
}
Possible use:
auto it = list_.before_begin();
for (auto& entry : list_)
{
(void)entry; //suppress warning
++it;
}
Now the iterator 'it' points to the last element

What does (void) mean in c++? [duplicate]

This question already has answers here:
Why cast an unused function parameter value to void?
(2 answers)
Closed 8 years ago.
I'm looking at some code that has a function that looks like this:
void f(A* a, B& b, C* c)
{
(void)a;
(void)b;
(void)c;
}
What exactly does the (void) at the start of every line do?
What you see there is really just a "trick" to fake variable/parameter usage.
Without those lines, a pedantic compiler will warn you about the variables not being used.
Using a construct (void)variablename; will result in no instructions being generated, but the compiler will consider it a valid "use" of those variables.
It's simply a kludge to avoid compiler warnings. For example, that code will emit
warning: unused parameter ‘a’ [-Wunused-parameter]
warning: unused parameter ‘b’ [-Wunused-parameter]
warning: unused parameter ‘c’ [-Wunused-parameter]
when compiled with gcc -Wall -Wextra if the kludge is not used. There are cleaner looking ways to achieve this though. You could omit the parameter names:
void f(A*, B&, C*) {
}
A gcc-specifc and somewhat verbose alternative is to use the unused attribute on each unused parameter:
void f(A* a __attribute__((unused)), B& b, C* c) {
}
I see at least two rerasons. The first one is to avoid warnings of the compiler that the variables are defined but not used in the body of the function.
The second one is that it is very old code and sometimes programmers wrote casting to void before expressions if the result of the expressions is not used. This helped the compiler to optimize generated object code.
Whenever we are writing a function in C++, we need to follow prototype of function, i.e.
type name ( parameter1, parameter2, ...) { statements }
here type- stands for type of value it returns
A return type of void allows you to define a function that does not return a value. Note that it is NOT the same as returning 0. The value of 0 is of type integer, float, double, etc; it is not a void. (In other languages, a function with no return value may be called a "subroutine" or "procedure", whereas a "function" always returns something. In C/C++, they are all called functions.)
returning void means returning nothing.
A pointer to void is a generic pointer that can be used when the type of the data at the location is unknown. So you can use a type of void * to refer to an address in memory without knowing what is actually located there.

reference to local variable returned: Why a warning? Why not an error? [duplicate]

This question already has answers here:
Why is returning a reference to a function local value not a compile error?
(6 answers)
Closed 8 years ago.
Consider the code:
int& getValue()
{
int i = 10;
return i;
}
This leads to compiler warning:
warning: reference to local variable `i' returned
I understand the reason for the warning. I am returning the reference to a local variable which is destroyed as soon as I go out of scope.
My question is: Why is this even allowed? Why doesn't the compiler simply give an error instead of a warning?
It is undefined behavior the compiler is not even obligated to provide a diagnostic let alone make it an error. The draft C++ standard in section 1.4 Implementation compliance says:
The set of diagnosable rules consists of all syntactic and semantic
rules in this International Standard except for those rules containing
an explicit notation that “no diagnostic is required” or which are
described as resulting in “undefined behavior.”
This is mainly due to the fact that it is not always trivial for the compiler to determine when undefined behavior is present and forcing the compiler to detect all cases would be considered an undue burden.
Although modern compilers are pretty good at catching all sorts of bad behavior include undefined behavior, with gcc and clang I find the following set of flags to be helpful: -Wall -Wextra -Wconversion -pedantic.
You can turn these into errors you can use -Werror which I recommend strongly. It forces you to understand why each warning is being generated and have the discipline to find better solutions which will save you a lot of pain in the long run.
Note, the one case where we can probably force an error for detectable undefined behavior is when we are assigning the result of a constexpr function to a constexpr variable since constant expression exclude undefined behavior.
So the following C++14 code:
constexpr int& getValue()
{
int i = 10;
return i;
}
int main()
{
constexpr int &p = getValue();
//...
}
generates the following error using clang:
error: constexpr variable 'p' must be initialized by a constant expression
constexpr int &p = getValue();
^ ~~~~~~~~~~
It's because what you're asking the compiler to compile can be compiler. Broadly speaking, errors are supposed to indicate that your code can't be comprehended; warnings merely indicate that you've possibly made a mistake (in this case: triggering undefined behaviour).

Why cast unused return values to void?

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 complete waste of time?
David's answer pretty much covers the motivation for this, to explicitly show other "developers" that you know this function returns but you're explicitly ignoring it.
This is a way to ensure that where necessary error codes are always handled.
I think for C++ this is probably the only place that I prefer to use C-style casts too, since using the full static cast notation just feels like overkill here. Finally, if you're reviewing a coding standard or writing one, then it's also a good idea to explicitly state that calls to overloaded operators (not using function call notation) should be exempt from this too:
class A {};
A operator+(A const &, A const &);
int main () {
A a;
a + a; // Not a problem
(void)operator+(a,a); // Using function call notation - so add the cast.
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.
The true reason for doing this dates back to a tool used on C code, called lint.
It analyzes code looking for possible problems and issuing warnings and suggestions. If a function returned a value which was then not checked, lint would warn in case this was accidental. To silence lint on this warning, you cast the call to (void).
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.
Since c++17 we have the [[maybe_unused]] attribute which can be used instead of the void cast.
Cast to void is costless. It is only information for compiler how to treat it.
For the functionality of you program casting to void is meaningless. I would also argue that you should not use it to signal something to the person that is reading the code, as suggested in the answer by David. If you want to communicate something about your intentions, it is better to use a comment. Adding a cast like this will only look strange and raise questions about the possible reason. Just my opinion...
As of C++11 you can also do:
std::ignore = fn();
This should achieve the same result on functions marked with [[nodiscard]]
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.
Also when verifying your code complies to MISRA (or other) standards, static-analysis 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)