Search code examples
arrayscfor-loopincrement

i++ and array positioning in c


#include <stdio.h>
#include <stdlib.h>

int main()
{
    int *k, j =10;
    k = calloc(j, sizeof(int));
    
    for(int i=0; i<j; i++){
    k[i] = (i++) +2;

    }
    
    printf("%d", k[3]);

    return 0;
}

i++ will increment the value of i, but return the original value that i held before being incremented

so the first iteration of the loop should translate to 'k[0] = 0++ +2;' which whould result in 'k[0] = 2;', after that 'i' would be equal to 1. And in the second iteration 'i' would equal to 2 because it gets the increment from the for loop and after the 'i++', so the loop would only return values to even positions 'k[0], k[2], k[4]';

then why 'k[3]' equals 4? it should be 0 because the iteration should only go through even values right?


Solution

  • In k[i] = (i++) +2;, i is used (a) in k[i] to index the array and (b) in i++ to increment i and produce its value before incrementing. The C standard does not specify any sequencing between (a) and (b). A C implementation is permitted to evaluate (a) before (b), to evaluate (b) before (a), or to intertwine them in various ways.

    Further, C 2018 6.5 2 says:

    If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined…

    In the above, (a) is a valuation computation using the value of the scalar object i. In (b), incrementing i is a side effect on the scalar object i. (That is a side effect because the main effect is to participate in evaluation of the expression.) Since this side effect and the value computation are unsequenced by the C standard, the behavior of the entire program is not defined by the C standard.

    In k[i] = (i++) +2;, the left operand, k[i] is evaluated to determine which array element to update. This is a value computation. (Even though it does not produce a numerical value, such as the value stored in k[i], it produces the information needed to identify the array element. This is called an lvalue.) (i++) +2 is evaluated to determine the value to store in the array element. Finally, the assignment causes the value of the right operand ((i++) +2) to be stored in the object identified by the left operand (k[i]). C 2018 6.5.16 3 tells us the store of the value is sequenced after the evaluation of the operands, but it does not tell us there is any sequencing for the value computations of the two operands. It explicitly says they are unsequenced:

    … The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.