views:

155

answers:

6

Bad style notwithstanding, is it legal C to have a for loop with braces inside the parens? Like this:

char *a = "a ";
char *b = "b ";

for ( { int aComesFirst = 1;
        char *first = a;
        char *second = b;
      };
      aComesFirst >= 0;
      { aComesFirst--;
        swap(first, second);
      } )
{
  printf("%s%s\n", first, second);
}

If something along those lines is possible, am I supposed to put a semicolon after the first close braces, or would that add an empty statement?

I do realize that it is stylistically better to move the char* declarations outside the for loop and the swap to the end of the inside of the loop. But style is not the point of this question, I just want to know if putting braces inside the parens is possible.

+6  A: 

No, it's not legal, but you can use commas to get half way there:

for (int a = 1, b = 2; a < 10; ++a, ++b)

You can't declare multiple variables of different types, and you can't use control structures in the last bit, but it's good enough most of the time.

If you didn't know, the comma used there is not some special syntax that can only be used in for loops, it's a general operator that can be used anywhere to evaluate the left operand, followed by the right operand, and return the result of the right expression, i.e. a, b == b, and a, b, c == c and so on.

Peter Alexander
Thanks! I'll accept your answer in a few minutes if it's still the best.
Jon Rodriguez
...and, frankly, the equivalent `while` structure will be clearer anyway. If you a determined to get limited scoping, just use a free standing `{}` block around the initialization-code-n-while-loop.
dmckee
+3  A: 

No, it is not legal. If it was legal the code wouldn't work anyway because c has block level scope, so you wouldn't have access to an of the variables defined in the braces.

mikerobi
Good point about block level scope.
Jon Rodriguez
+2  A: 

That's not legal but this is:

for(i = 0, j = 10; i < 10; i++, j--)
{
  // ..
}

See: the comma operator

Dinah
++ for the link to "the comma operator". I didn't know that comma was a first-class and so useful operator.
Jon Rodriguez
+8  A: 

I've answered this before… this can easily be made legal in C or C++ by adding a local struct type. It's generally poor style, though.

char *a = "a ";
char *b = "b ";

for ( struct loopy { int aComesFirst;
        char *first;
        char *second;
      } l = { 1, a, b }; /* define, initialize structure object */

      l.aComesFirst >= 0; /* loop condition */

      l.aComesFirst--, /* loop advance */
      swap(l.first, l.second)
    )
{
  printf("%s%s\n", l.first, l.second);
}
Potatoswatter
`struct loopy` Ah! +1 love the tag; -1 Arrrggghhhh; result +0
pmg
++ for hacking the loop into actually working; the only direct answer to my question. And yeah, that's as stylish as bell bottoms.
Jon Rodriguez
There are probably compilers out there that will allow you to omit `loopy` and `l` to declare an anonymous object of anonymous type, so you can pretend it doesn't exist.
Potatoswatter
A: 

The Standard says (6.8.5.3/1)

for ( clause-1 ; expr-2 ; expr-3 ) statement

I'm pretty sure neither expr-2 or expr-3 can be replaced by something not an expression (a block is not an expression), and I'm pretty sure clause-1 also cannot be replaced by a statement.

pmg
+1 for the relevant citation and to counter whoever the downvoting idiot was.
R..
+1  A: 

Are you using the gcc with Statement Expressions? http://tigcc.ticalc.org/doc/gnuexts.html#SEC63 Maybe that will make that type of code work. except it's (int i = { stmts; }; { stmts; bool}; { ... })

SHiNKiROU
++ Thanks for showing me the Statement Expressions extension.
Jon Rodriguez