int [] arr = {0}; int value = arr [arr [0] ++]; 值= 1?

Gal*_*you 12 c# operator-precedence

今天我来了Eric Lippert撰写的一篇文章,他试图清除运算符优先级和评估顺序之间的神话.最后有两个代码片段让我感到困惑,这是第一个片段:

      int[] arr = {0};
      int value = arr[arr[0]++];
Run Code Online (Sandbox Code Playgroud)

现在,当我考虑变量值的值时,我只是将其计算为1.这就是我认为它的工作方式.

  1. 首先将arr声明为int数组,其中包含一个项目; 这个项目的值是0.
  2. 在这种情况下,第二个得到arr [0] --0的值.
  3. 第三个得到arr的值[步骤2的值](仍为0) - 再次指定arr [0] - 仍然为0.
  4. 第四步将步骤3(0)的值赋给变量值.--value = 0现在
  5. 添加到步骤2的值1 - 现在arr [0] = 1.

显然这是错的.我试图在c#规范中搜索关于何时实际发生增量但没有找到任何增量的明确声明.
第二个片段来自Eric 关于该主题的博客文章的评论:

 int[] data = { 11, 22, 33 }; 
 int i = 1;
 data[i++] = data[i] + 5;
Run Code Online (Sandbox Code Playgroud)

现在这是我认为该程序将执行的方式 - 在声明数组并为i分配1之后.[跟我一起]

  1. 获取数据[i] --1
  2. 将值5 - 6添加到步骤1的值
  3. 分配给data [i](仍为1)步骤2的值--data [i] = 6
  4. 增量i - i = 2

根据我的理解,这个数组现在应该包含值{11,27,33}.但是,当我循环打印我得到的数组值时:{11,38,33}.这意味着,增量提领该阵列之前发生了!
怎么会?这个帖子增量不应该发布吗?即发生在其他一切之后.
我想念的是什么人?

Jon*_*eet 18

后增量操作作为评估整体表达的一部分发生.这是在评估值之后但在评估任何其他表达式之前发生的副作用.

换句话说,对于任何表达式E,E ++(如果合法)表示类似(伪代码):

T tmp = E;
E += 1;
return tmp;
Run Code Online (Sandbox Code Playgroud)

在评估其他任何东西之前,这都是评估E ++的一部分.

有关更多详细信息,请参阅C#3.0规范的第7.5.9节.


另外,对于将LHS分类为变量的分配操作(如本例所示),在评估RHS 之前评估LHS .

所以在你的例子中:

int[] data = { 11, 22, 33 }; 
int i = 1;
data[i++] = data[i] + 5;
Run Code Online (Sandbox Code Playgroud)

相当于:

int[] data = { 11, 22, 33 }; 
int i = 1;
// Work out what the LHS is going to mean...
int index = i;
i++;
// We're going to assign to data[index], i.e. data[1]. Now i=2.

// Now evaluate the RHS
int rhs = data[i] + 5; // rhs = data[2] + 5 == 38

// Now assign:
data[index] = rhs;
Run Code Online (Sandbox Code Playgroud)

规范的相关部分是第7.16.1节(C#3.0规范).

  • 除了运算符优先级否则指示时,从左到右计算表达式(包括赋值).因此,在右侧的data [i]之前评估data [i ++](赋值的左侧). (3认同)

Vot*_*ple 5

对于第一个片段,序列是:

  1. 如你所述声明arr:
  2. 检索arr [0]的值,即0
  3. 将arr [0]的值增加到1.
  4. 检索arr [(#2的结果)]的值,即arr [0],其中(每#3)为1.
  5. 存储结果value.
  6. 值= 1

对于第二个片段,评估仍然是从左到右.

  1. 我们在哪里存储结果?在data [i ++]中,数据[1],但现在i = 2
  2. 我们添加什么?data [i] + 5,现在是数据[2] + 5,即38.

缺少的部分是"发布"并不意味着"在其他一切之后".它只是意味着"在我检索到该变量的当前值之后立即".在"一行代码"中间发生的后增量是完全正常的.