Ferruccio
Ferruccio

Reputation: 100648

Why can't I put a variable declaration in the test portion of a while loop?

You can, obviously, put a variable declaration in a for loop:

for (int i = 0; ...

and I've noticed that you can do the same thing in if and switch statements as well:

if ((int i = f()) != 0) ...

switch (int ch = stream.get()) ...

But when I try to do the same thing in a while loop:

while ((int ch = stream.get()) != -1) ...

The compiler (VC++ 9.0) does not like it at all.

Is this compliant behavior? Is there a reason for it?

EDIT: I found I can do this:

while (int ch = stream.get() != -1) ...

but because of precedence rules, that's interpreted as:

while (int ch = (stream.get() != -1)) ...

which is not what I want.

Upvotes: 22

Views: 30092

Answers (6)

user3458
user3458

Reputation:

The problem is, the standard permits you a declaration inside parenthesis. What you want to do is to get a declaration as part of expression, which is something that standard will not let you do.

while() can have one of two syntaxes: while(<declaration>) or while(<expression>). The declaration uses "=", and looks like expression, but it's a different syntactical entity.

When you write

while(int i = 1) {
}

, that's perfectly fine. "int i=1" is a declaration. However, what you want is

while ( (int i = 1) + 3) {
}

This is a very different animal. You want an expression inside while(), where one of the terms of the expression is a declaration. Now, declaration is a statement, and as such cannot be part of expression. That's why what you need to be done cannot be done.

(after writing the whole rant, I noticed that 2 other people wrote the same thing. Oh well, the more the merrier.)

Upvotes: 16

Mark Ransom
Mark Ransom

Reputation: 308138

Try This doesn't work

while (int ch = stream.get(), ch != -1) ...

I've never tried it, but if the comment in your edit is correct, this should work.
VS 2005 won't even compile it.

Upvotes: 0

Richard Corden
Richard Corden

Reputation: 21721

The grammar for a condition in the '03 standard is defined as follows:

condition:
  expression
  type-specifier-seq declarator = assignment-expression

The above will therefore only allow conditions such as:

if ( i && j && k ) {}
if ( (i = j) ==0 ) {}
if ( int i = j ) {}

The standard allows the condition to declare a variable, however, they have done so by adding a new grammar rule called 'condition' that can be an expression or a declarator with an initializer. The result is that just because you are in the condition of an if, for, while, or switch does not mean that you can declare a variable inside an expression.

Upvotes: 15

MSalters
MSalters

Reputation: 179799

You can put a variable declaration in the test expression of a while loop. What you cannot do is put a declaration statement in other expressions. For instance, in the expression a+b+c, you cannot replace b by int i = f(). And the same hold for the expression (a); you can't insert int i=f() to get an expression (int i=f()).

So, in while (int i = foo()), the outermost brackets are part of the while statement, and not of the text-expression, and everything is legal. In while ((int i = foo())), the outermost brackets are still part of the while statement. The test-expression would have the form "(" expr ")", and you end up with a syntax error.

Upvotes: 2

workmad3
workmad3

Reputation: 25677

This doesn't appear to be compliant behaviour. Part 6.5.1.2 of the standard states:

When the condition of a while statement is a declaration, the scope of the variable that is declared extends from its point of declaration (3.3.1) to the end of the while statement. A while statement of the form

while (T t = x) statement

is equivalent to

label:
{ //start of condition scope
    T t = x;
    if (t) {
        statement
        goto label;
    }
}

So in your example, ch should be declared within the scope of the loop and work correctly (with it being recreated through each loop iteration). Reason for the observed behaviour is most likely due to the compiler not scoping the variable correctly and then declaring it multiple times.

Upvotes: 11

RB.
RB.

Reputation: 37192

It might be because the contents of the while clause are evaluated each loop, thus it would try and declare "ch" multiple times.

The if, switch, and for loop examples you gave will all have "ch" being defined only once.

Upvotes: 2

Related Questions