arrayscvariable-assignment

Confusion about post-decrement and assignment execution order in C


I'm confused about the behavior of the post-decrement (i--) and pre-decrement (--i) operators in C, especially when used in the context of array indexing and assignment. I'm trying to understand the execution order between the decrement and the assignment operation.

Here is my code:

#include <stdio.h>

int main() { 
    int arr1[] = {11, 12, 13, 14, 15, 16}; 
    int arr2[] = {21, 22, 23, 24, 25, 26};
    int i = 5;
    
    arr1[i--] = arr2[i];        //1st assignment
    
    int arr3[] = {11, 12, 13, 14, 15, 16};
    int arr4[] = {21, 22, 23, 24, 25, 26};
    
    int j = 5;
    
    arr3[j] = arr4[j--];        //2nd assignment
    
    return 0;
}

What I expected:

What actually happened:

Question:

Why does the second assignment (arr3[j] = arr4[j--];) result in modifying arr3[4] instead of arr3[5]? I thought the post-decrement should use the current value before decrementing, so both indices should be 5 in this case. Could this be due to sequence point rules or undefined behavior?


Solution

  • Both invoke undefined behaviour (UB) as i and j have undefined value because of the sequence point1 problems.

    What I expected:

    As it is Undefined Behaviour you should have not been expecting anything.

    Always enable all warnings and in most cases the compiler will warn you:

    
    <source>: In function 'main':
    <source>:6:11: warning: operation on 'i' may be undefined [-Wsequence-point]
        6 |     arr1[i--] = arr2[i];        //1st assignment
          |          ~^~
    <source>:13:21: warning: operation on 'j' may be undefined [-Wsequence-point]
       13 |     arr3[j] = arr4[j--];        //2nd assignment
          |                    ~^~
    
    

    You need split it into two statements:

    arr1[i] = arr2[i];
    i--;
    
    arr3[j] = arr4[j];
    j--;
    

    1. [There’s no sequence point (no guaranteed evaluation order) between the LHS and RHS, nor between those two uses of i/j. So the read and the modification are unsequenced relative to each other → UB]