Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

How come in C++ when you put:

while (expression);

the while loop doesn't run no matter if the expression is true or not.

However if you put:

if (expression);

the statement runs no matter if the expression is true or not.

It seems like they should both behave the same way.

share|improve this question
3  
They do behave the same way, although if the while loop is infinite it might take kind of a long time to reach the next statement. –  Karl Bielefeldt Jun 25 '13 at 22:05
    
Both constructs "run", i.e., expression gets evaluated. Depending on the side effects of evaluating expression or whether expression involves volatile variables, the outcome may vary. –  mouviciel Jun 26 '13 at 7:24
    
Section 1.10.24 of the c++ standard allows the compiler to remove the while loop entirely without proving it is not infinite under certain circumstances. –  JohnB Jun 26 '13 at 14:30

4 Answers 4

Your statement that gets run (or not) is an empty statement, the ;. The other statements that follow the ; have nothing to do with your if- and while-statement. Your code would do the same when written as

while (expression)
{
    ;
}

and

if (expression)
{
    ;
}

The only difference is that your statement would be inside a block. You could add more statements inside the block (inside the curly brackets) that would get executed, if the expression was true.

share|improve this answer

actually when you put

while(expr);

then if expr is true then you get into an infinite loop that will never end (so the remaining code never executes)

you can understand it by replacing the empty statement ; with a no-op

void noop(){}

while(expr)noop();

then the semantics make sense

share|improve this answer
    
Ok that makes sense, although I still don't see why if(expr); should run when it's false while while(expr); doesn't run when it is false. –  pajamas Jun 25 '13 at 20:48
2  
because the block after the if(expr); is not part of the if anymore. that's also why if(expr);{...}else{...}is a compiler error –  ratchet freak Jun 25 '13 at 20:52
    
But shouldn't that mean then the block after while is no longer part of it and thus should also run? –  pajamas Jun 25 '13 at 21:24
1  
@pajamas yes it does, when expr is false then it will run –  ratchet freak Jun 25 '13 at 21:27
3  
@pajamas: If expr evaluates to 0 (a false value), then if (expr); and while (expr); do the same thing: they evaluate expr and do nothing else. After that, any immediately following statements are executed. –  Keith Thompson Jun 26 '13 at 0:03

The syntax is:

if (<expr>) <statement>

// or

while (<expr>) <statement>

So the statement (in both cases) is only executed if the expression evaluates to true. In the case of while it will enter a loop (re-evaluating express each time).

So the question what <statement> is executes. This comes down to the definition of statement. If there are not braces {} then the next statement is terminated by ; even if that statement is EMPTY. An empty statement is valid;

if (<expr>)    /* Empty Statement */;

while (<expr>) /* Empty Statement */;

In both cases there is nothing being executed (after the expression is evaluated). Though while may enter an infinite loop. Note: '{}' is a statement-Block (a type of statement (that contains a list of other statement).

Note:

It is considered bad form to use empty statements with for(;;) or while() or if(). It is often hard to spot and when people do spot it they are not entirely sure the code is correct (and may have to spend time de-bugging the code to verify correctness).

I find it best to use '{}` after each of these to emphasis the point (and catch multi=statement macros).

for(<init>;<test>;<inc>) { /*Deliberately blank */ }
share|improve this answer

They both run, as has been pointed out in other answers.

Consider the canonical string concatenator while(*s1++ = *s2++); once s1 and s2 have been initialized. expr in this case is *s1++ = *s2++, and the body of the while loop is the empty statement ;. Remember that in C, the value of an assignment is the assigned value, so this could be rewritten as

while((*s1++ = *s2++) != 0)
{
}

and have the same effect (with possible variations in performance depending on optimizations performed by the compiler).

Your confusion likely does stem from the fact that if and while are both followed either by a single statement, or a single statement block. When you put a semicolon statement terminator after the condition part, they become semantically equivalent to:

while(expr)
{
}
{
    /* do something */
}

and

if(expr)
{
}
{
    /* do something */
}

which are both perfectly valid code (you can have an empty block, or a block without an associated flow control statement) but probably don't do what you want.

If expr is constant, which is often the case when no constituent variables are modified inside the (empty) loop, then the while loop will either skip the empty statement block (if expr evaluates to false) or turn into an infinite loop executing the empty statement (if expr evaluates to true).

You can check this by giving expr a non-breaking side effect, such as logging a message or increment some internal static or member state variable:

while(log_message(), expr);

and observe that the log_message() function gets called repeatedly.

Assuming that your code is something like:

int x = 0;
while (x < 1234);
{
    x++;
}
/* do more... */

it should now be obvious why your program doesn't do what you expect, as the above is semantically equivalent to:

int x = 0;
while (x < 1234)
{
}
{
    x++;
}
/* do more... */

Since x never gets modified inside the while loop's statement block (because it is empty), the expression x < 1234 will never evaluate to anything other than true, and hence you have an infinite loop. If the expression was instead x != 0 the empty statement block would instead be skipped over because the while loop's condition evaluates to false, you would reach the x++ and end up with x == 1 at the point of /* do more... */.

If the condition was instead something like ++x < 1234, then x would simply be incremented (++x evaluated), and the empty statement-block executed, until the condition is true, after which the while loop finishes and execution continues with a single pass through what you intended to do a number of times.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.