11

I found strange macros in a driver implementation that I can't explain to myself. Simplified example is:

cout << ({int i=0; while(i<10) {++i;} i;}) << endl;

It will output 10.

But why this does expression become an rvalue at all? It seems to work in C and in C++.

Can someone explain me? Pointing to keywords and to reference will be great.

fuz
  • 88,405
  • 25
  • 200
  • 352
johngull
  • 819
  • 6
  • 22
  • Putting `int i=0; while(i<10) {++i;} i;` inside a block surrounded by `( )` makes printf to treat it like a function. At and it reads the last i and print it. – Michi Dec 24 '15 at 13:59
  • 1
    This can't work in C. C doesn't support overloaded `<<` operators. – fuz Dec 24 '15 at 14:00
  • @FUZxxl [What makes you saying that](http://ideone.com/jLUk7j)? – Michi Dec 24 '15 at 14:01
  • @Michi Please read my full comment, not just the first sentence. – fuz Dec 24 '15 at 14:01
  • @FUZxxl did you expected from OP to show `C` and `C++` code ? – Michi Dec 24 '15 at 14:02
  • 7
    Incidentally, finally you can obtain (mostly) the same result in standard C++ using a lambda function and calling it immediately: `cout << ([](){int i=0; while(i<10) {++i;} return i;}()) << endl;` (replace `[]` with `[&]` if you need to reference variables of the surrounding function) – Matteo Italia Dec 24 '15 at 14:03
  • @MatteoItalia thank you. I know how to make it with lambda, just was curious why such construction works. – johngull Dec 24 '15 at 14:05
  • @FUZxxl sorry for confusing you, sure i made example for C++, but the expression inside () works for both C and C++. And as explained here already - this is GCC extention – johngull Dec 24 '15 at 14:06
  • @johngull If you try something like this `printf("%d",{int i=0; while(i<10) {++i;} i;});` won't work, because there is an Expression expected, but if you surround the whole block with `()` the `printf` function will treat it as a function – Michi Dec 24 '15 at 14:09

1 Answers1

15

The is a GCC extension:

A compound statement enclosed in parentheses may appear as an expression in GNU C.

The last thing in the compound statement should be an expression followed by a semicolon; the value of this subexpression serves as the value of the entire construct.

Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
  • @Borgleader: check the link. "This feature is especially useful in making macro definitions “safe” (so that they evaluate each operand exactly once)" – Karoly Horvath Dec 24 '15 at 14:00
  • 1
    @Borgleader: also, because there are places in C++ where only expressions are allowed, while often you'd want to write "real" code - think members initialization. (More in general, the statement/expression dicothomy is entirely artificial and often gets in the way, having some way to escape it is always a Good Thing) – Matteo Italia Dec 24 '15 at 14:04
  • "the statement/expression dicothomy is entirely artificial" - true, it's a language design choice. Comparing with ruby, where *everything* is an expression (great expressive power), or python, which is very strict (=safe, can catch potential problems like = vs ==), c/c++ is somewhere in the middle ground, but definitely not in a sweet-spot. The weird comma operator is a good evidence that something fishy is going on... – Karoly Horvath Dec 24 '15 at 14:26