【问题标题】:C assignes wrong index in array [duplicate]C在数组中分配错误的索引[重复]
【发布时间】:2015-11-30 12:33:09
【问题描述】:

我有密码

#include <stdio.h>
int main(){
    int y [10]; int i = 1;
    y[i] = i++;
    printf("y0: %d\n", y[0] );
    printf("y1: %d\n", y[1] );
    printf("y2: %d\n", y[2] );
}

我认为那行

y[i] = i++; 

应该作为 y[1] = 1;然后将 i 设置为 2;

但是 y[1] 有一些随机值,并且 y[2] 设置为 1。为什么?

【问题讨论】:

  • ++i 首先增加i 的值,然后返回一个lvalue,所以如果使用i 的值,那么它将是新的增加值. i++ 首先返回一个rvalue,其值为i,即旧值,然后在下一个完整表达式之前的未指定时间递增i
  • 如果它看起来很狡猾,(并且 y[i] = i++; 确实如此),而你只是认为它会起作用,你为什么要使用它?为什么你不把它分开以便你知道它是如何工作的?我不明白你为什么要在这里发布这样的 rubbi.. 代码,而不是采取明显且简单的步骤来修复它。

标签: c arrays variables increment


【解决方案1】:

您处于未定义行为的领域。在某些编译器上它可能工作,在其他编译器上可能不行。

问题是在行

y[i] = i++;

i 被计算了两次,你不能假设它是赋值之前还是之后的表达式。

如果首先计算 i++,则表达式结果变为 1。但在计算 y[i] 之前它会递增。所以 i == 2 然后创建 y[2] = 1; 如果 i 在赋值之前首先被评估,则结果变为 y[1] = 1; i++;

将其更改为当然会修复它:

y[i] = i;
i++;

【讨论】:

  • 是的,我知道这是未定义的行为,但如果我得到:y[2]=1,这是不可能的。因为如果先做 i++ 然后索引数组它会是 y[2]=2,如果先取左边它会是 y[1]=2 或 y[1]=1
  • @dsadsadsadsad 不,这不是未定义的行为。这与i=i++ 的情况不同。
  • @dsadsadsadsad 未定义行为意味着没有预期的、可预测的行为。该程序可能会崩溃,因为打印某种输出,或者什么也不做。等等。不要与未指定的行为混淆,程序将以某种我们无法提前知道的方式运行,但至少它不会停止并着火。
  • @ameyCU 副作用的数量并不是唯一可以使表达 UB 的东西。标准中有两个句子(6.5)。你指的是第一个: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. 但是直接在那句话之后:If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.
  • @ameyCU C99 在 imo 上说得更清楚: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 read only to determine the value to be stored. 73) Note 73) 给出了一个几乎相同的例子:This paragraph renders undefined statement expressions such as i = ++i + 1; a[i++] = i;
【解决方案2】:

需要使用循环来更新'y'值

// for loop execution
for( int i = 0; i <= 2; i++ )
{
    y[i] = i;
}
printf("y0: %d\n", y[0] );
printf("y1: %d\n", y[1] );
printf("y2: %d\n", y[2] );

【讨论】:

  • 是的,没错。更新。 :)
  • 我已经在第一次编辑中做到了。
  • 我知道我应该使用循环,但我想看看当我使用 y[i]=y++ 时会发生什么,我使用 y[0,1,2] 来看看刚刚发生了什么跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-19
  • 2013-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-28
相关资源
最近更新 更多