Search code examples
clanguage-lawyerundefined-behavior

Are these expressions involving compound literals defined in C?


Are these expressions defined?

    int x = 5, y;
    y = ++(int){++x};
    //or 
    y = (int){x++}++;

and (I cant find any reason why not to be defined)

    int x = 5;
    x = ++(int){++x};
    //or 
    x = (int){x++}++;

IMO there are clear sequence points where new object (compound literal) is created.


Solution

  • These are fine:

    y = ++(int){++x};
    y = (int){x++}++;
    

    As no object is being read or written more than once, specifically x, y, and the unnamed compound literals. Modifying the compound literal is also not a problem because (in this case) it has automatic storage duration and so its lifetime is that of the enclosing block, even though it will be unaccessible due to its address not being taken.

    In contrast these trigger undefined behavior:

    x = ++(int){++x};
    x = (int){x++}++;
    

    Because x is modified more than once without a sequence point, as use of a compound literal does not introduce a sequence point.

    Section 6.8p4 of the C standard states the following (not the bolded part):

    A full expression is an expression that is not part of another expression or of a declarator. Each of the following is a full expression: an initializer that is not part of a compound literal; the expression in an expression statement; the controlling expression of a selection statement (if or switch); the controlling expression of a while or do statement; each of the (optional) expressions of a for statement; the (optional) expression in a return statement. There is a sequence point between the evaluation of a full expression and the evaluation of the next full expression to be evaluated.

    In the example above, because ++x is part of the initializer of a compound literal, it does not qualify as a full expression and therefore there is no sequence point introduced by the compound literal.