squeevee
squeevee

Reputation: 161

c/c++ using else instead of if not

Encountered a bit of weird-looking code and it got me wondering if there's any practical application to it, or if it's just a random oddity.

The code essentially looks like this:

#ifdef PREPROCESSOR_CONDITION
    if (runtime_condition) {
    } else
#endif
    {
        //expression
    }

I included the macro bit, though I doubt it has any bearing. There's no code that runs when runtime_condition is true, only the else block. I figure this ought to be completely identical to using if(!runtime_condition) and no else block (which would have been more straightforward), but maybe there's some kind of compiler-optimizey thing happening?

Or, you know, it could be that there used to be something in the if block that got deleted and nobody bothered to change the expression.

Upvotes: 2

Views: 153

Answers (2)

Alex Celeste
Alex Celeste

Reputation: 13370

Ensuring the conditional definitely always has two branches (on those occasions when it is compiled as a conditional) guarantees that someone who works on a platform that always has PREPROCESSOR_CONDITION defined won't absent-mindedly add a real else block below, which clearly isn't how this block is supposed to work (or worse, "fix" it so that their code does compile everywhere, but in the process damage whatever the intent of the original author was in constructing their blocks that way).

If that is the intent, it would normally make sense to communicate it explicitly by hiding the exact details of the if-empty-else behind a macro named something like UNLESS, though.


It definitely isn't anything to do with optimization. If you think in terms of the jumps involved, a compiler already has to invert the value of the predicate to decide whether to skip the block or not (i.e. if (A) {B;} C:... really means if (!A) goto C; B; C:...), which means it folds the hand-written ! at the outermost level of the expression into the conditional's structure anyway; since most instruction sets will provide both jump-if-true and jump-if-not-true instructions, doing this is completely free, and both ways to write "if not" in the source will produce the same machine code on even a very simple compiler without any optimization.

Upvotes: 2

Peter
Peter

Reputation: 36597

The "macro bit" is significant.

Consider what happens if the programmer mistakenly changes the snippet to

#ifdef PREPROCESSOR_CONDITION
if (runtime_condition)
{
}
else
#endif
{
    //expression
}
else
{
    // another expression
}

This will result in a compilation error, regardless of whether PREPROCESSOR_CONDITION is defined or not.

With your change, viz;

#ifdef PREPROCESSOR_CONDITION
if (!runtime_condition)
#endif
{
    //expression
}
else
{
    // another expression
}

it will compile if PREPROCESSOR_CONDITION is defined, but fail if it is not defined.

If the programmer who adds the else only attempts compilation in conditions with PREPROCESSOR_CONDITION defined, no problem will be found. There will then be a latent defect in the code, that will not be exposed until the code is compiled with PREPROCESSOR_CONDITION undefined.

This may seem minor in a single code snippet, but compilation errors occurring by surprise (e.g. code breaking in unexpected places) is a significant productivity concern if it occurs in larger projects.

Upvotes: 2

Related Questions