Does 'a[i] = i;' always result in well defined behaviour?

后端 未结 6 1404
忘了有多久
忘了有多久 2021-02-05 11:19

There are several interesting questions raised here regarding undefined behaviour in C. One of them is (slightly modified)

Does the following piece of code r

相关标签:
6条回答
  • 2021-02-05 11:47

    int i = 0, *a = &i;

    there is a sequence point between declarations, therefore no UB here. However take a note that it is a bad idea to declare/define variables that way. Any normal coding standard would tell you declare one variable per line.

    a[i] = i;

    The i is not changed in any way, therefore no UB here either.

    0 讨论(0)
  • 2021-02-05 11:58

    This will result in undefined behavior in C++03, and well-defined behavior in C++11.

    C++03: Undefined Behvaior

    From the C++03 standard, section 5 paragraph 4:

    Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored.

    Note the second sentence: The previous value of i can only be used to determine the value to be stored. But here it is also used to determine the array index. So because this assignment will modify i, a[0] = i+1 is well defined, while a[i] = i+1 is not. Note that the assignment does not generate a sequence point: only the end of the full expression (the semicolon) does.


    C++11: Well defined behavior:

    C++11 got rid of the notion of sequence points, and instead defines which evaluations are sequenced before which.

    From the standard, section 1.9 paragraph 15:

    The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.

    Both operands of the assignment operator are sequenced before the actual assignment. So both a[i] and i+1 will be evaluated, and only then will i be modified. The result is well defined.

    0 讨论(0)
  • 2021-02-05 12:05

    No it doesn't. The first line has a sequence point (the comma), so it is not undefined behaviour:

    int i = 0, *a = &i;
    

    The second line is perfectly normal.

    a[i] = i + 1;
    

    Since i + 1 creates a temporary value, i gets modified only once, on the assignment. This however would be undefined behaviour:

    a[i] = i++;
    
    0 讨论(0)
  • 2021-02-05 12:06

    Let us decompose the expression a[i] = i + 1 will you ?

    = -- [] -- a
      \     \_ i
       \
        \_ + -- i
             \_ 1
    

    Effectively, a[i] refers to &i however note that neither a[i] nor i+1 modifies i. i is only modified when = (the assignment itself) is executed.

    Since the operands of any function need be evaluated before this function takes effect, this is actually equivalent to:

    void assign(int& address, int value) { address = value; }
    
    assign(a[i], i + 1);
    

    It is true that = is somewhat special in that it is built-in and does not result in a function call, still the evaluation of both operands are sequenced before the actual assignment, so they are first evaluated prior to i being modified, and a[i] (which points to i location) is being assigned to.

    0 讨论(0)
  • 2021-02-05 12:08

    Undefined behavior in this case would only take place if you modify the same memory address without a sequence point between the modifications. Specifically, the C99 spec, section 6.5/2 states,

    Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored.

    In your case no modification of the same memory address takes place between sequence points, therefore there is no undefined behavior.

    0 讨论(0)
  • 2021-02-05 12:14

    I would like to point out one thing: a[i] = i does not always lead to well defined behaviour. The reason why the behaviour is well defined in the case specified, is because of the initial values i and a.

    Let me elaborate:

    int i = 1, *a = &i;   // Line 1, i initialized to anything other than 0
    a[i] = i + 1;         // Line 2, all of a sudden we are in buffer over/underflow
    

    For any other initial value of i we are accessing a different memory location from that of i itself, which produces undefined behaviour.

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