5

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.

AlcubierreDrive
  • 3,654
  • 2
  • 29
  • 45

6 Answers6

9

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
  • 134,909
  • 25
  • 265
  • 421
  • 1
    `struct loopy` Ah! +1 love the tag; -1 Arrrggghhhh; result +0 – pmg Oct 03 '10 at 23:51
  • ++ for hacking the loop into actually working; the only direct answer to my question. And yeah, that's as stylish as bell bottoms. – AlcubierreDrive Oct 03 '10 at 23:51
  • 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 Oct 03 '10 at 23:57
  • The above compiles only if `swap()` is an expression (e.g., a non-void function, or macro whose expansion returns a value). – Jeff Learman Jul 21 '20 at 17:49
  • 1
    @JeffLearman The third part of `for` may be `void`. – Potatoswatter Jul 21 '20 at 18:13
  • @Potatoswatter I'm not objecting to that; I'm objecting to the use of a void expression with the comma operator, which used to be illegal. Evidently it's legal now, or at least gcc allows it. – Jeff Learman Jul 21 '20 at 19:10
7

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
  • 53,344
  • 14
  • 119
  • 168
3

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
  • 20,527
  • 5
  • 46
  • 42
2

That's not legal but this is:

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

See: the comma operator

Dinah
  • 52,922
  • 30
  • 133
  • 149
1

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}; { ... })

Ming-Tang
  • 17,410
  • 8
  • 38
  • 76
0

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
  • 106,608
  • 13
  • 126
  • 198