Reputation: 584
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
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
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