Are these expressions involving compound literals defined in C?
Asked Answered
M

1

5

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.

Moulden answered 11/9, 2023 at 12:58 Comment(12)
With clang I get a warning for the second snippet: warning: multiple unsequenced modifications to 'x' [-Wunsequenced]Bay
For the second code snippet, the line x = ++(int) { ++x }; gets a warning from clang-cl: warning : multiple unsequenced modifications to 'x' [-Wunsequenced]. But not for y = ++(int) { ++x };.Hurff
I think x = (int){x++}++; is unspecified behavior, since x is modified twice (the inner ++ and the outer assignment). It would be the same with x = x++;Couscous
Even without the second (outer) increment, clang gives the same warning for x = (int) { ++x };.Hurff
The first thing I'm surprised about is that curly brace expression syntax. Shouldn't those be (round) parentheses?Moderate
You claim that there are "clear sequence points where a compound literal is created" but I can find no such statement in "Annex C (Sequence Points)" of this C17 Draft Standard.Hurff
@Moulden The last assignment makes two assignments to x: One with the = operator and one with the ++ operator.Couscous
@Peter Compound LiteralsHurff
The issue with the last assignment is answered here. You can't make an assignment to x from an expression that modifies x.Couscous
@AdrianMole Sure; but an int is not a struct, union or array. Do the braces create an anonymous struct, or an array, with a single int member? Which is incremented? What would that even mean?Moderate
There are really two questions here: One is whether it's ok to modify compound literals, and the other is a duplicate of this.Couscous
Even 3 DVs and countingMoulden
L
12

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.

Letta answered 11/9, 2023 at 13:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.