0

Sorry I can't name those things properly, if I could, I might not have to ask. The latter part is probably also a statement because of the semicolon, but it's just a "a + b" which doesn't do anything?

I recently saw this thread and its accepted answer: MIN and MAX in C

Using this macro:

#define max(a,b) \
({ __typeof__ (a) _a = (a); \
   __typeof__ (b) _b = (b); \
 _a > _b ? _a : _b; })

I examined it to understand how it works, i.e. how that produces something which, upon macro expansion, can be assigned to something else. So here a simpler example which compiles and does what it seems to:

int x = ({ int a=5; int b=3; a + b; });
printf( "%i", x );
// output: 8

Why / how does this work exactly, and why are both brace pairs ({ }) necessary for it to compile/work?

Community
  • 1
  • 1
user1847129
  • 1,010
  • 2
  • 9
  • 21
  • Possible duplicate of [what is the purpose of "(void) ( { CODE } )" in c?](http://stackoverflow.com/questions/13210673/what-is-the-purpose-of-void-code-in-c) – Martin R Apr 28 '17 at 11:20
  • Possible duplicate of [What is it called when a block returns a value?](http://stackoverflow.com/questions/8344101/what-is-it-called-when-a-block-returns-a-value). – Martin R Apr 28 '17 at 11:23
  • Also related: http://stackoverflow.com/questions/1635549/in-what-versions-of-c-is-a-block-inside-parenthesis-used-to-return-a-value-valid. – Martin R Apr 28 '17 at 11:28
  • 1
    Consider dropping the obsolete, non-standard `__typeof__` for standad C `_Generic` – Lundin Apr 28 '17 at 11:57

3 Answers3

3

This is a GCC feature called a statement expression. It's not part of standard C.

It works as you've inferred - the code inside the expression runs, and then the expression evaluates to the value of the last statement inside it.

({ and }) are necessary because that's what the creators of GCC decided - probably so that it wouldn't be possible to confuse with anything else.

user253751
  • 57,427
  • 7
  • 48
  • 90
2

This is a GCC-specific extension. It is not standard-conforming, and is unlikely to work in majority of compilers. I guess it wouldn't have to require those parentheses, but having them makes it more visually obvious, and also makes its inadvertent use less likely.


By default GCC allows non-standard extensions without any diagnostics - if you compile with say -std=c11 -pedantic, you will get

% gcc -std=c11 -pedantic foo.c
foo.c: In function ‘main’:
foo.c:4:12: warning: ISO C forbids braced-groups within expressions [-Wpedantic]
    int x = ({ int a=5; int b=3; a + b; });
            ^
1

This is a so-called Statement Expression, which is not standard-compliant.

Recall that C has statements and expressions. Statements do things without producing a value, while expressions always produce a value at the end.

C allowed expressions to be used as statements from the beginning. However, there was no syntax to make statements into expressions.

GCC extension restores the symmetry: when you enclose curly braces in parentheses, and have an expression at the end of your statement block, gcc takes this as a valid expression. This trick allows you to make declarations inside the statement, but you can put any other expression in curly braces, for example

int x = ({
    int i = 0;
    for (int j = 0 ; j != 6 ; j++) {
        i += j;
    }
    i; // <<== This expression serves as a "return" for the statement
});
printf("%d\n", x);

Above, the entire for loop is part of a single initializer expression of variable x.

This program prints 15.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523