18

Sorry for the vague title, but not really sure how to phrase it. So I was looking through the innards of boost::asio (trying to track down some ridiculous delays), and I notice code like this dotted about:

    op_queue<operation> completed_ops;
    task_cleanup c = { this, &lock, &completed_ops };
    (void)c;  // EH?

Now from the name of the struct that is being initialized, I'm guessing it's using RAII to do some steps on destruction - fine, but what is the purpose of the last line? Have I just missed something completely funky?

John Carter
  • 53,924
  • 26
  • 111
  • 144
Nim
  • 33,299
  • 2
  • 62
  • 101
  • possible duplicate of [Why is (void) 0 a no operation in C and C++?](http://stackoverflow.com/questions/2198950/why-is-void-0-a-no-operation-in-c-and-c) – hammar May 26 '11 at 21:56
  • @hammar : I don't think he's asking why it's a noop, I think he's asking why bother having the statement at all. – ildjarn May 26 '11 at 21:57
  • @ildjarn, correct - and now in hindsight, feel rather stupid.. blame lack of sleep.. : – Nim May 26 '11 at 21:58
  • Why not ask whoever wrote it? –  May 26 '11 at 22:00
  • 4
    @Neil Butterworth, it's not an asio specific question, why would Chris bother answering? It's a question about the particular syntax, and evidently there is a simple explanation - which eluded me in my sleep deprived state... – Nim May 26 '11 at 22:04

3 Answers3

19

Maybe to avoid a compilation warning because c isn't used?

tibur
  • 11,531
  • 2
  • 37
  • 39
  • 1
    Is it possible that an overzealous optimizing compiler can optimize away the construction/destruction of `c` as well since it's never used? Or can that only happen for primitive types? – Wyatt Anderson May 26 '11 at 21:57
  • Exactly. And I believe the cast to (void) is to avoid warnings from lint, believe it or not. – Nemo May 26 '11 at 22:06
  • 3
    @Wyatt Anderson, I doubt that, the compiler cannot possibly predict all the side effects of constructor/destructor esp. if they are non-trivial. – Nim May 26 '11 at 22:08
4

It's probably there because it's a cross-platform method of getting the compiler not to complain about an unused variable.

jwismar
  • 12,164
  • 3
  • 32
  • 44
3

The question was probably meant to be about why it's used, and that's already been answered. I'm going to talk about what it means (which the OP probably already knows, but others may not). At least one other question has been closed as a duplicate of this one.

In general, casting an expression to void evaluates the expression and discards the result, if any. In this case, the expression is c, the name of a variable of type task_cleanup (whatever that is).

An expression followed by a semicolon is an expression statement. When the statement is executed, the expression is evaluated and its result is discarded.

So this:

(void)c;

evaluates c (which, since c is just a non-volatile declared object, just fetches the value of the object), then discards the result, then discards the result again.

Semantically, this doesn't make much sense. You might as well just write:

c;

or even omit it entirely with exactly the same effect.

The purpose, as the other answers have already said, is to suppress a warning that the variable's value is not used. Without the cast, many compilers will warn that the result is discarded. With the cast, most compilers will assume that you're deliberately discarding the value, and will not warn about it.

This is no guarantee; compilers can warn about anything they like. But casting to void is a sufficiently widespread convention that most compilers will not issue a warning.

It probably would have been worthwhile to call the variable ignored rather than c, and a comment would definitely be helpful.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631