What does casting to `void` really do?

C++CastingCompiler WarningsVoidSuppress Warnings

C++ Problem Overview


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?

C++ Solutions


Solution 1 - C++

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.

Solution 2 - C++

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++.

Solution 3 - 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);
}

Solution 4 - C++

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRuslanView Question on Stackoverflow
Solution 1 - C++Rahul TripathiView Answer on Stackoverflow
Solution 2 - C++John ZwinckView Answer on Stackoverflow
Solution 3 - C++Arne VogelView Answer on Stackoverflow
Solution 4 - C++TraummaennleinView Answer on Stackoverflow