Interdependent initialization with commas?

后端 未结 2 1281
谎友^
谎友^ 2021-01-02 03:44

Is the following perfectly defined:

int x = 42, y = x;

i.e. strictly equivalent to:

int x = 42;
int y = x;
<
相关标签:
2条回答
  • 2021-01-02 03:48

    This question came up in comp.lang.c++.moderated a long time ago under the topic init-declarator-list analysis order and the conclusion there was Yes.

    Although I see the full-expression argument but I do not see the order of evaluation argument. So I think this is unspecified.

    The relevant part of the question is:

    In this declaration and definition:

    int a = 2, b = a;

    Is it guaranteed that b will always be initialized as 2 ? If yes, then can we say that a = 2 is always analysed(or evaluated?) before b = a ?

    and the relevant part of the answer is:

    Yes. Strictly stated, the observable behavior of the program must be as if all of the side effects of the 'a = 2' part of the declaration took place before the evaluation of the 'b = a' part starts. (In practice, of course, in this simple example, a compiler could assign 2 to both a and b in any order, or even in parallel, because doing so would result in the same observable behavior.)

    and further down:

    In this particular case, however, it does separate the declarator list into separate declarators; each declarator contains a complete expression, and the declarators are evaluated in order.

    Update

    What makes each init-declator a full expression is subtle but as far as I can tell follows the same logic I used in Are multiple mutations of the same variable within initializer lists undefined behavior pre C++11. In this case we start from the grammar defined in ection 8:

    init-declarator-list:
      init-declarator
      init-declarator-list , init-declarator
    init-declarator:
      declarator initializeropt
    

    The next point of focus is the initializer grammar which is covered in section 8.5:

    initializer:
      brace-or-equal-initializer
      ( expression-list )
    brace-or-equal-initializer:
      = initializer-clause
      braced-init-list
    initializer-clause:
      assignment-expression
      braced-init-list
    

    In both cases we have = initializer-clause which bring us to assignment-expression which if we follow the grammar in section 5 bring us back to primary-expression which can give us either a literal or id-expression.

    So we do indeed have full-expressions separated by a grammatical comma so we have:

    int x = 42, y = x;
              ^      ^
              |      end full-expression
              end full-expression
    

    and according to section 1.9 paragraph 14 we see that:

    Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.8.

    As for the order of evaluation, I think this is not specified, the same logic that applies to defect report 430 for initializer lists would seem to apply here as well. In C++11 the language for initializer lists was fixed with the following addition in section 8.5.4:

    Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (14.5.3), are evaluated in the order in which they appear. [...]

    there is no such equivalent for initializer.

    0 讨论(0)
  • 2021-01-02 04:06

    The correct answer is that

    int x = 42, y = x;
    

    and

    int x = 42;
    int y = x;
    

    are usually equivalent (not strictly).


    Considering the standard § 8 Declarators [dcl.decl]:

    3 Each init-declarator in a declaration is analyzed separately as if it was in a declaration by itself.

    and in the footnote [100] further explains:

    A declaration with several declarators is usually equivalent to the corresponding sequence of declarations each with a single declarator. That is

    T D1, D2, ... Dn;

    is usually equivalent to

    T D1; T D2; ... T Dn;

    where T is a decl-specifier-seq and each Di is an init-declarator.

    • The above guarantees that x = 42 and y = x will be evaluated separately. However, as @Praetorian correctly pointed out in the comments, footnotes are not normative.

    • This means that the order of evaluation is not well defined and an implementer could as well implement the evaluation of the declarations in the reverse order (i.e,. T Dn; ...T D2; T D1;).

    • One might argue that the comma operator is guaranteed left to right evaluation. However, this not the case. According to the K & R [K & R II, 3.6 p.63], that also applies to C++:

    The commas that separate function arguments, variables in declarations, etc., are not comma operators, and do not guarantee left to right evaluation.

    0 讨论(0)
提交回复
热议问题