nwn
nwn

Reputation: 584

GCC evaluation of compound statement

I found the following construct, where a variable is assigned to what seems to be a compound statement, foo, in a driver. For comparison, bar yields undefined behaviour be treating the same code as a proper function. It doesn't seem to conform with my understanding of the C language and its preprocessor, so I suspect that it is a GCC extension. What is the logic executed here? (See output here.)

#include <stdio.h>

#define foo(c) ({ int x = c; x; })

int bar(char c) {
    int x = c;
    x;
}

int main(void) {
    int x = foo('0');
    int y = bar('A');
    printf("%d\n%d\n", x, y);
    return 0;
}

Output:

48
0

Upvotes: 0

Views: 1032

Answers (2)

AnT stands with Russia
AnT stands with Russia

Reputation: 320481

There are two different things involved here.

Firstly, the so called "statement expression" ({ int x = c; x; }), which is a GCC extension. This expression in GCC evaluates to the well-defined value of x. The value it evaluates to is defined by the last expression inside the ({...}), which is x in your case. (BTW, the preprocessor has little to do with it. You don't have to involve preprocessor to use statement expressions in GCC.)

Secondly, your function bar, which is declared to return int but lacks a return statement. This has nothing to do with any extensions. This function does not return any defined value. If the calling code attempts to use the value returned by bar, the behavior is undefined. The x expression at the end of bar is just a no-op that does not change anything.

Upvotes: 2

rici
rici

Reputation: 241721

It is indeed a GCC extension and it is described in the GCC manual. Where an expression is expected, you can supply a brace-surrounded block as a valid expression whose value is the last expression in the block.

C does not automatically insert a return in an expression statement at the end of a function, so bar is indeed UB. GCC does not implement any extension which does that either. But the following would be legal with the GCC extension:

int bar(char c) {
  return ({
    int x = c; 
    x; 
  });
}

Upvotes: 2

Related Questions