Why is an empty if allowed?

M

Marcel Müller

Hi,

I recently had a bug where I accidentally wrote

if (condition); // <--
{ // code block
}

I did not even get a compiler warning about that (gcc 3.3.5). But the
question is, why this should be allowed at all. It makes no sense as it
will always be equivalent to
condition;
including side effects - in contrast to
while (condition);
which is obviously meaningful. However, I would prefer
while (condition) {}
for clearness.


Marcel
 
F

Francesco S. Carta

Hi,

I recently had a bug where I accidentally wrote

if (condition); // <--
{ // code block
}

I did not even get a compiler warning about that (gcc 3.3.5). But the
question is, why this should be allowed at all. It makes no sense as it
will always be equivalent to
condition;
including side effects [...]

I don't know if there is any rationale for explicitly allowing a
construct like that, maybe it's just an harmless oversight. The
important thing would be to see if the compiler is able to optimize away
the "if" while keeping the side effects of the "condition" expression,
if any. If there is no side effect at all, the compiler could (and
hopefully will) completely ignore the entire instruction.

By the way, also MinGW 4.4.0 accepts it without a crease.
 
R

Rolf Magnus

Marcel said:
Hi,

I recently had a bug where I accidentally wrote

if (condition); // <--
{ // code block
}

I did not even get a compiler warning about that (gcc 3.3.5). But the
question is, why this should be allowed at all.

One would need to add an extra rule to the C++ standard just to forbid that.
There lots of cases where it's possible to write code that doesn't make
sense. Forbidding them all would make the standard much more complicated
with only a very small benefit.
 
M

Marcel Müller

Pete said:
if (!a)
;
else if (b)
do_something();
else
do_something_else();

Intresting point. But you are right. In this case it makes a difference.

Of course, I don't want to overstate this case with the empty if
statement. It took me 20 years of C/C++ to cause the first bug.


Marcel
 
G

Goran Pusic

It's useful for a particular style of writing complex decisions:

if (a)
        {
        if (b)
                do_something();
        else
                do_something_else();
        }

can be rewritten as

if (!a)
        ;
else if (b)
        do_something();
else
        do_something_else();

;-)

Hey, you! Why are you trying to hide the intention of the code?
(Intention being do anything __only__ if condition a is met.)

Goran.
 
G

Goran Pusic

It's not hidden at all. If you're used to the style, it's quite clear,
and far more readable than the original version.

'course it's hidden. Look:

(reading...) if (!a) (thinking: OK, let's see what happens if "!a"...)
(reading...) ; (thinking: actually, "nothing happens". Why are you
having "nothing" here?
(reading...) else if (b) (thinking: else to what? (goes up, reads "!
a", converts
"else of !a" to if (a), continues).

Contrast this to:

(reading...) if (a) (thinking: OK, let's see what happens if a...)
(reading...) { (reading what happens if a...)

IOW, my problem is that you just used double negation to achieve
affirmation and you called that more readable. I am not impressed ;-),
and IMO you need more complex code to warrant the style.

Goran.
 
J

Juha Nieminen

Marcel Müller said:
But the
question is, why this should be allowed at all. It makes no sense as it
will always be equivalent to
condition;

One could use the feature for something like:

if(something) assert(another_condition);
 
V

Vladimir Jovic

Pete said:
Please don't mistake "I haven't seen this before" with "this is wrong".
As I said, if you're used to it, it's much clearer. I won't bother going
through the silly exercise of what you might look at when; that just
reflects your current habits, not ultimate truth.,

hmmm why this conversation sounds so familiar?

Ah, I know :

ps Sorry I couldn't resist :)
 
J

James Kanze

Please don't mistake "I haven't seen this before" with "this is wrong".
As I said, if you're used to it, it's much clearer. I won't bother
going through the silly exercise of what you might look at when; that
just reflects your current habits, not ultimate truth.,

Independently of whether you've seen it or not... It depends on
the higher level program logic you're implementing. If the
logic is "if a then x else if b then y else z", and x happens to
be nothing, then the most logical way of translating this into
C++ is:
if (a)
;
else if (b)
y;
else
z;
Anything else if obfuscation.

For that matter, people tend to read positives more easily than
negatives, and I can easily imagine cases (where the condition
a is non trivial) where I'd write:
if (a)
;
else
y;
If a is reasonably complicated (with perhaps some parts negated,
etc.), I'd prefer this to:
if ( ! (a) )
y;

And of course, there are some conditions you can't invert:
if ( T* p = dynamic_cast<T*>(baseP) )
;
else
// baseP is not a T, so we have to do something.
(Of course, one might argue why the variable here. But since it
is in scope in the else, even if its value is guaranteed
null...)
 
G

Goran Pusic

Please don't mistake "I haven't seen this before" with "this is wrong".

Well, now... Please don't try to imply knowing what I saw before or
not. That said, in the interest of perfect honesty, I do not remember
seeing __your__ trick, but I do remember writing empty "ifs" and
"elses" __myself__, with comments as to what happens elsewhere if the
"empty" block is hit.

And please don't imply words coming out of my mouth (well, keyboard).
I did not say that this is wrong (it demonstratively isn't wrong, per
se), I said that you are hiding intention of the code.

Other than that, note that you failed to address my main point: you're
using double negation to achieve confirmation. My contention is:
that's obfuscation, and it's unwarranted.

Note also that I tried having being lighthearted, as I put winkies in
my first post and used humorous tone (well, or so I thought). I have
also been relatively conservative in my criticism, when I said that
you need more complex example to warrant the style.
I won't bother
going through the silly exercise of what you might look at when; that
just reflects your current habits, not ultimate truth.

Ah. Well, if you want to speak about the "ultimate truth" in things
like this, then I guess we're really not on the same page.

Goran.
 
G

gwowen

It's useful for a particular style of writing complex decisions:

if (a)
        {
        if (b)
                do_something();
        else
                do_something_else();
        }

can be rewritten as

if (!a)
        ;
else if (b)
        do_something();
else
        do_something_else();

Having said that, if you disallow

if(cond);

you can still do

if (!a) {}
else if (b) do_something();
else do_something_else();

Purely personally, I think the latterlooks like an intentionally empty
statement, whereas the former looks like a typo...
 
K

Keith H Duggar

It's useful for a particular style of writing complex decisions:

if (a)
        {
        if (b)
                do_something();
        else
                do_something_else();
        }

can be rewritten as

if (!a)
        ;
else if (b)
        do_something();
else
        do_something_else();

Also it can be used to coax the compiler into improved static
branch prediction. For example, if your compiler assumes that
forward conditional branches are not taken and if !a is the
most common path then

if ( !a ) {
} else {
//true condition, forward branch code
}

might produce more optimal code than

if ( a ) {
//true condition, no longer forward branch code
}

KHD
 
G

Goran

        If a is true, then either b is true, in which case do action number 1, or b is
        false, in which case, do action number 2.

The first one is obviously clearer, despite the "double negation".

If a is true, then we'll do X.
X is: if b is true we'll do something, otherwise we'll do something
else.

The above is division into smaller chunks, a mighty popular way of
decomposing problems.

Your method is "put all in one bag and sort it out all at once". That
approach does not scale and you know it. Also, my contention is that
it's still unwarranted in a simple example like yours.

Goran.
 
T

Timothy Madden

Hi,

I recently had a bug where I accidentally wrote

if (condition); // <--
{ // code block
}

I did not even get a compiler warning about that (gcc 3.3.5). But the
question is, why this should be allowed at all. It makes no sense as it
will always be equivalent to
condition;
including side effects - in contrast to
while (condition);
which is obviously meaningful. However, I would prefer
while (condition) {}
for clearness.

The C++ syntax simply says that after the condition some statement must
follow, and ";" is a statement.

That is really all there is to it :)

Good luck,
Timothy Madden
 
G

Goran Pusic

Since you know better than I do what it is that I know there's no need
for me to participate in this discussion any further. You can just fill
in my parts for me. That will make things go much faster, since you
won't have to read anything that doesn't fit your world view.

Well, I was merely attempting to support my argument with more general
view on things: when solving problems, divide and conquer is generally
regarded as better than juggling pieces together. I implied knowing
that you know that. I put this to you, then: can you honestly and
claim that you don't realize that? My guess is: you do know that.

In your example, problem is trivially divisible into
* did "a" occur?
* do the "b" part

But, in the case of your example, you prefer to mix it together
because problem space is small.

I'll reiterate all the reasons I can think of problems with your
trick, then I'll stop, honest ;-) :

1. using double negation to achieve affirmation is obfuscation
(mitigation: example has a really low obfuscation factor)
2. your code still has more artifacts than mine ("your way" has 4 ifs
and elses, "mine" has 3; mitigation: penny-pinching)
3. your code mixes things together that can be trivially separated and
handled so
4. (wasn't mentioned before) some compilers warn about your construct

Goran.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,263
Messages
2,571,062
Members
48,769
Latest member
Clifft

Latest Threads

Top