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

发布于 2024-07-30 12:48:02 字数 1290 浏览 2 评论 0原文

今天,我看到了 Eric Lippert 撰写的一篇文章,他试图澄清运算符优先级之间的迷思以及评估的顺序。 最后有两个代码片段让我感到困惑,这是第一个片段:

      int[] arr = {0};
      int value = arr[arr[0]++];

现在,当我考虑变量 value 的值时,我只是将其计算为 1。 这就是我认为它是如何工作的。

  1. 首先声明 arr 为 int 数组 里面有一件物品; 这 item 的值为 0。
  2. 其次获取 arr[0] --0 中的值 这个案例。
  3. 第三步获取arr的值[值 步骤 2](仍然是 0)--gets arr[0]再次--仍然是0。
  4. 第四次分配步骤3的值 (0) 为变量值。 --值= 0 now
  5. 添加到步骤 2 的值 1 --Now arr[0] = 1。

显然这是错误的。 我尝试在 C# 规范中搜索一些有关增量何时实际发生的明确声明,但没有找到任何内容。
第二个片段来自 Eric 的评论 关于该主题的博客文章

 int[] data = { 11, 22, 33 }; 
 int i = 1;
 data[i++] = data[i] + 5;

现在我认为这个程序将如何执行——在声明数组并将 1 分配给 i 之后。 [请耐心听我说]

  1. 获取 data[i] --1
  2. 将步骤 1 的值添加到该值 5 --6
  3. 赋值给data[i](仍然是1) 步骤2的值 --data[i] = 6
  4. Increment i -- i = 2

根据我的理解,这个数组现在应该包含值{11, 27, 33}。 但是,当我循环打印数组值时,我得到:{11, 38, 33}。 这意味着 post 增量发生在取消引用数组之前!
怎么会? 这个岗位增量不应该是岗位吗? 即发生在其他一切之后。
伙计们,我错过了什么?

Today I came a cross an article by Eric Lippert where he was trying to clear the myth between the operators precedence and the order of evaluation. At the end there were two code snippets that got me confused, here is the first snippet:

      int[] arr = {0};
      int value = arr[arr[0]++];

Now when I think about the value of the variable value, I simply calculate it to be one. Here's how I thought it's working.

  1. First declare arr as an array of int
    with one item inside of it; this
    item's value is 0.
  2. Second get the value of arr[0] --0 in
    this case.
  3. Third get the value of arr[the value
    of step 2] (which is still 0) --gets
    arr[0] again --still 0.
  4. Fourth assign the value of step 3
    (0) to the variable value. --value =
    0 now
  5. Add to the value of step 2 1 --Now
    arr[0] = 1.

Apparently this is wrong. I tried to search the c# specs for some explicit statement about when the increment is actually happening, but didn't find any.
The second snippet is from a comment of Eric's blog post on the topic:

 int[] data = { 11, 22, 33 }; 
 int i = 1;
 data[i++] = data[i] + 5;

Now here's how I think this program will execute --after declaring the array and assigning 1 to i. [plz bear with me]

  1. Get data[i] --1
  2. Add to the value of step 1 the value
    5 --6
  3. Assign to data[i] (which is still 1)
    the value of step 2 --data[i] = 6
  4. Increment i -- i = 2

According to my understanding, this array now should contain the values {11, 27, 33}. However, when I looped to print the array values I got: {11, 38, 33}. This means that the post increment happened before dereferencing the array!
How come? Isn't this post increment supposed to be post? i.e. happen after everything else.
What am I missing guys?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

泼猴你往哪里跑 2024-08-06 12:48:02

后递增操作作为计算整个表达式的一部分发生。 这是在计算值之后但在计算任何其他表达式之前发生的副作用。

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

T tmp = E;
E += 1;
return tmp;

这是计算 E++ 的全部部分,然后再计算其他内容。

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


此外,对于 LHS 被分类为变量的赋值操作(如本例所示),LHS 在评估 RHS 之前评估。

因此,在您的示例中:

int[] data = { 11, 22, 33 }; 
int i = 1;
data[i++] = data[i] + 5;

相当于:

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;

规范的相关位是第 7.16.1 节(C# 3.0 规范)。

The postincrement operation occurs as part of evaluating the overall expression. It's a side effect which occurs after the value is evaluated but before any other expressions are evaluated.

In other words, for any expression E, E++ (if legal) represents something like (pseudo-code):

T tmp = E;
E += 1;
return tmp;

That's all part of evaluating E++, before anything else is evaluated.

See section 7.5.9 of the C# 3.0 spec for more details.


Additionally, for assignment operations where the LHS is classified as a variable (as in this case), the LHS is evaluated before the RHS is evaluated.

So in your example:

int[] data = { 11, 22, 33 }; 
int i = 1;
data[i++] = data[i] + 5;

is equivalent to:

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;

The relevant bit of the specification for this is section 7.16.1 (C# 3.0 spec).

雨落星ぅ辰 2024-08-06 12:48:02

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

  1. 按照您的描述声明 arr:
  2. 检索 arr[0] 的值,即 0
  3. 将 arr[0] 的值增加到 1。
  4. 检索 arr[(#2 的结果) 的值] 是 arr[0],(根据 #3)是 1。
  5. 将该结果存储在 value 中。
  6. value = 1

对于第二个片段,计算仍然是从左到右。

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

缺少的一点是“post”并不意味着“在其他所有事情之后”。 它只是意味着“在我检索该变量的当前值之后立即”。 在一行代码的“中间”发生后增量是完全正常的。

For the first snippet, the sequence is:

  1. Declare arr as you described:
  2. Retrieve the value of arr[0], which is 0
  3. Increment the value of arr[0] to 1.
  4. Retrieve the value of arr[(result of #2)] which is arr[0], which (per #3) is 1.
  5. Store that result in value.
  6. value = 1

For the second snippet, the evaluation is still left-to-right.

  1. Where are we storing the result? In data[i++], which is data[1], but now i = 2
  2. What are we adding? data[i] + 5, which is now data[2] + 5, which is 38.

The missing piece is that "post" doesn't mean "after EVERYTHING else." It just means "immediately after I retrieve the current value of that variable." A post increment happening "in the middle of" a line of code is completely normal.

浅唱ヾ落雨殇 2024-08-06 12:48:02
data[i++] // => data[1], then i is incremented to 2

data[1] = data[2] + 5 // => 33 + 5
data[i++] // => data[1], then i is incremented to 2

data[1] = data[2] + 5 // => 33 + 5
溺孤伤于心 2024-08-06 12:48:02

我希望后递增运算符在使用变量的值后递增变量。
在这种情况下,变量在第二次引用该变量之前递增。

如果不是这样,你可以写

data[i++] = data[i++] + data[i++] + data[i++] + 5

如果它像你说的那样,那么你可以删除增量运算符,因为它实际上没有做任何事情,在我报告的指令中。

I would expect the post-increment operator to increment the variable after its value is used.
In this case, the variable is incremented before the second reference to the variable.

If it would not be so, you could write

data[i++] = data[i++] + data[i++] + data[i++] + 5

If it would be like you say, then you could remove the increment operator because it doesn't do actually anything, in the instruction I reported.

2024-08-06 12:48:02

您必须分三个步骤考虑赋值:

  1. 计算左侧(=获取应存储值的地址)
  2. 计算右侧
  3. 将步骤 2 中的值分配给步骤 1 中的内存位置。

如果您有类似的内容

A().B = C()

那么 A () 将首先运行,然后 C() 将运行,然后属性设置器 B 将运行。

本质上,你必须将你的陈述视为

StoreInArray(data, i++, data[i] + 5);

You have to think of assignments in three steps:

  1. Evaluate left hand side (=get address where the value should be stored)
  2. Evaluate right hand side
  3. Assign the value from step 2 to the memory location from step 1.

If you have something like

A().B = C()

Then A() will run first, then C() will run, and then the property setter B will run.

Essentially, you have to think of your statement as

StoreInArray(data, i++, data[i] + 5);
另类 2024-08-06 12:48:02

原因可能是某些编译器将 i++ 优化为 ++i。 大多数时候,最终结果是相同的,但在我看来,这是编译器错误的罕见情况之一。

我现在无法访问 Visual Studio 来确认这一点,但请尝试禁用代码优化并查看结果是否保持不变。

The cause might be that some compilers optimize i++ to be ++i. Most of the time, the end result is the same, but it seems to me to be one of those rare occasions when the compiler is wrong.

I have no access to Visual Studio right now to confirm this, but try disabling code optimization and see if the results will stay the same.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文