Search code examples
cgccgcc-statement-expression

Using comma operator (a, b) when a is a block of code


#include <stdio.h>

int main()
{
    int sum = 0, result = (({for (int i = 0; i < 5; i++) sum += i;}), sum);
    
    printf("result = %d\n", result);

    return 0;
}

displays

result = 10

I'm using whatever the default version of C is in gcc. Is it specific to gcc? I'm aware (a, b) returns b but I didn't expect to get it to work when a was a {} block. Can anyone explain why it works and why the block has to be bracketed to get it to work?

EDIT: This is a contrived simplified example of a #define I was trying out. Some programmer dude's comment (thanks) clears it up. Case closed.


Solution

  • I'm using whatever the default version of c is in gcc.

    Currently that's -std=gnu17, equivalent to "lax ISO C17 with GNU extensions". It is not a conforming mode and not recommended for beginners.

    Is it specific to gcc?

    Yes, or rather it is specific to the GNU C dialect, which is at least partially supported by clang as well. As mentioned in comments, this is a non-standard extension known as "statement expressions" or "statements in expressions". It allows multiple expressions/lines and optionally returns a value like a function-like macro.

    I'm aware (a, b) returns b but I didn't expect to get it to work when a was a {} block

    The comma operator has a special evaluation rule guaranteeing that the sub-expression a is fully evaluated before b. Normally this isn't the case with C operators. This means that you can assume that everything at a is executed before b and you may even safely include code using b.

    However, a list of variables to be initialized does not come with such a sequencing guarantee. int sum = 0, result=sum; does not guarantee any particular order or sequencing - code such as this is deeply problematic and possibly undefined behavior.


    Best practices are to follow standard C whenever possible, to write code as readable as possible and to avoid poorly-defined behavior. Complex "one-liner" code is very bad practice. So this would have been much better written as:

    int sum = 0;
    for (int i=0; i < 5; i++) 
    {
      sum+=i;
    }
    int result = sum;
    

    Or if you prefer, the 100% equivalent:

    int result = 10;