C[i] = A[i++];不等于 C[i] = A[i];我++;这里发生了什么?

C[i] = A[i++]; is not equal to C[i] = A[i]; i++; Whats going on here?

我尝试使用循环展开以不同方式遍历数组。

#define MYSIZE 8

int main()
{
    int A[MYSIZE];
    int B[MYSIZE];
    int C[MYSIZE];

    int i = 0;
    while(i < MYSIZE)
    {
        A[i] = i;
        i++;
    }

    /* LOOP 1 */
    i = 0;
    while (i< MYSIZE)
    {
        B[i+0] = A[i+0];
        B[i+1] = A[i+1];
        B[i+2] = A[i+2];
        B[i+3] = A[i+3];
        i += 4;
    }

    /* LOOP 2 */
    i = 0;
    while (i < MYSIZE)
    {
        C[i] = A[i++];
        C[i] = A[i++];
        C[i] = A[i++];
        C[i] = A[i++];
    }

    printf(" i | A | B | C|\r\n");
    i = 0;
    while (i < MYSIZE)
    {
        printf(" %d | %d | %d | %d |\r\n",i,A[i],B[i],C[i]);
        i++;
    }
}

哪个确实给了我这个结果:

 i | A | B | C |
 0 | 0 | 0 | 1578166688 |
 1 | 1 | 1 | 0 |
 2 | 2 | 2 | 1 |
 3 | 3 | 3 | 2 |
 4 | 4 | 4 | 3 |
 5 | 5 | 5 | 4 |
 6 | 6 | 6 | 5 |
 7 | 7 | 7 | 6 |

我认为 A、B 和 C 应该包含相同的数字。 据我了解 i++LOOP 2 应该与:

/* LOOP 3 */
i = 0
while(i < MYSIZE)
{
    C[i] = A[i];
    i++;
    C[i] = A[i];
    i++;
    C[i] = A[i];
    i++;
    C[i] = A[i];
    i++;
}

事实并非如此。 LOOP 3 实际上工作正常但 LOOP 2 没有。我做错了什么?

这个表达式:

 C[i] = A[i++];

调用 undefined behavior 因为变量 i 的读取和写入都没有序列点。

虽然在赋值给左侧之前必须对赋值的右侧进行完全求值,但每个子表达式的求值都是无序的,i 的副作用也是如此正在递增。

C standard 第 6.5.16p3 节中关于赋值运算符的详细说明:

An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue. The type of an assignment expression is the type the left operand would have after lvalue conversion. 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.

在这个具体的例子中,i的值可以先被读取用作C的索引,然后它可以作为i++的一部分被读取和写入右侧的表达式。或者,可以先评估 i++ 并递增,然后可以读取 i 以用作 C.

的索引

i 的递增应该作为单独语句的一部分来避免这种情况。

C[i] = A[i];
i++;

根据 dbush 的响应,我使用附加变量进行了测试以避免发生这种情况,并得到了预期的结果。

/* LOOP 2 */
i = 0;
int j = 0;
while (i < MYSIZE)
{
    C[j++] = A[i++];
}