5

Something I've used but never understood is the ability in C++ to write code like:

#include <stdio.h>

void sideEffect()
{
    printf("Hello, I'm a side effect\n");
}

int main()
{
    printf(({sideEffect(); "Hello side effect\n";}));
    return 0;
}

This prints:

Hello, I'm a side effect
Hello side effect

The ({ expr1; expr2; }) part seems to run the block and 'replace' the whole thing with the last value.

Is this is just a consequence of operator precedence that I'm not getting, or is there something else going on?

UPDATE

Something non-obvious (for me at least) is that the last expression is copied, even if it's returning a reference. I added a simple Foo class that prints when it's being copied to the example above:

...

struct Foo
{
    Foo()
    {}
    Foo(const Foo&)
    {
        printf("Copying Foo...\n");
    }
};

const Foo& getFoo()
{
    static Foo f;
    return f;
}

int main()
{
    const Foo& foo = ({sideEffect(); getFoo();});
    return 0;
}

The output:

Hello, I'm a side effect
Copying Foo...

If Foo is noncopyable this won't compile

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Xiao
  • 1,552
  • 2
  • 22
  • 20
  • 6
    This is a language extension. You can use the comma operator instead (but please for the love of rightfold just use multiple statements and variables). –  May 22 '14 at 21:34
  • 1
    Many dups are there, just not tagged C++ but common extension for both C & C++. One here: http://stackoverflow.com/questions/13210673/what-is-the-purpose-of-void-code-in-c – P.P May 22 '14 at 21:38
  • Excellent, thanks for that. I figured there would be others, but I couldn't for the life of me find them – Xiao May 22 '14 at 21:44
  • 1
    I've never heard of this extension before – Mooing Duck May 22 '14 at 21:52

2 Answers2

8

This is an extension to the C and C++ languages that GCC implements. It's called Statement Expressions.

I'll copy a bit from their documentation below:

Recall that a compound statement is a sequence of statements surrounded by braces; in this construct, parentheses go around the braces. For example:

({ int y = foo(); int z;
   if (y > 0) z = y;
   else z = - y;
   z;
})

is a valid (though slightly more complex than necessary) expression for the absolute value of foo ().

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. (If you use some other kind of statement last within the braces, the construct has type void, and thus effectively no value.)

As noted by GCC's documentation, it's often used in macros:

#define maxint(a,b) \
   ({int _a = (a), _b = (b); _a > _b ? _a : _b; })
Community
  • 1
  • 1
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • Great, thanks. Do you if this is supported by other popular compilers like Clang? EDIT: Seems it won't in pedantic mode: http://stackoverflow.com/questions/20661836/implementing-min-and-max-in-clang-without-double-evaluation – Xiao May 22 '14 at 21:50
0

What you are seeing is two distinct PrintF calls, which is why they show on two separate lines. When the program enters

printf(({sideEffect(); "Hello side effect\n";}));

It will immediately call sideEffects method which will subsequently call a new unique printF statement

printf("Hello, I'm a side effect\n");

but, since the sideEffects has no return (void) it will not have any bearing on the original printF statement leaving only the string literal "Hello side effect\n" in the output.

Jwit
  • 156
  • 6