Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is "({ expr1; expr2; })" compiled in C++? [duplicate]

Tags:

c++

syntax

gcc

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

like image 242
Xiao Avatar asked May 22 '14 21:05

Xiao


1 Answers

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; })
like image 118
Bill Lynch Avatar answered Oct 21 '22 08:10

Bill Lynch