【问题标题】:C[i] = A[i++]; is not equal to C[i] = A[i]; i++; Whats going on here? [duplicate]C[i] = A[i++];不等于 C[i] = A[i];我++;这里发生了什么? [复制]
【发布时间】:2020-05-10 23:48:20
【问题描述】:

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

#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 不能。我做错了什么?

【问题讨论】:

  • 循环 2 (C[i] = A[i++];) 导致未定义的行为。循环 1 或循环 3 是执行您尝试的正确方法。
  • 但是为什么呢? LHS 和 RHS 评估的顺序不是确定性的吗?
  • 如果ii++ 之间没有序列点,则它们的行为是“不确定的”。并且作业没有。
  • 是的,谢谢大家回答我的问题 :)
  • @Ambadrant 如果答案解决了您的问题,请考虑accepting it

标签: c loops post-increment


【解决方案1】:

这个表达式:

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

调用undefined behavior,因为变量i在没有序列点的情况下被读取和写入。

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

C standard 的第 6.5.16p3 节对赋值运算符进行了详细说明:

赋值运算符将值存储在左操作数指定的对象中。一个 赋值表达式具有赋值后左操作数的值,但不是 一个左值。赋值表达式的类型是左操作数的类型 左值转换后。 更新左操作数的存储值的副作用是 在左右操作数的值计算之后排序。的评价 操作数未排序。

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2015-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-04
      • 1970-01-01
      • 1970-01-01
      • 2012-11-23
      相关资源
      最近更新 更多