C# 的运算符操作顺序

发布于 2024-12-17 06:38:25 字数 218 浏览 1 评论 0原文

我正在将 C++ 实用程序移植到 C#。当我在 C++ 中运行以下语句时,我得到了正确的操作。然而,当我在 C# 中运行相同的语句时...

omgwtfbbq

有谁知道为什么执行 'begin++' ?疯狂的是,如果我运行 (i % 2) == 0 且 i=0,则立即窗口返回 true。

I am porting a C++ utility to C#. When I run the following statement in C++, I get the correct operation. When I run the same statement in C#, however...

omgwtfbbq

Does anyone know why 'begin++' is executed? The crazy thing is that if I run (i % 2) == 0 with i=0, the Immediate Window returns true.

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

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

发布评论

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

评论(3

谁对谁错谁最难过 2024-12-24 06:38:25

运算符优先级与这个问题无关。导致此行为的是评估顺序。

在 C# 中,i++i % 2 之前计算,因为它位于左侧。因此,i % 2 为 false,并且 if 的右侧被评估。

首先,您使用优先级来获取语法树:

=
  buffer[i++]
  if i % 2
    then temp[end--]
    else temp[begin++]

在每个节点上,您从左到右评估子节点。这意味着 i++i % 2 之前计算。

Eric Lippert 在 SO 和他的博客上有很多关于此的帖子:

就我个人而言,我会避免这样的代码。将其拆分为多个表达式,甚至使用简单的 if 语句而不是 会更好吗? :


在 C++ 中,访问中间没有序列点的变量是未定义的行为。我认为 = 不是序列点,所以我猜你的表达式在 C++ 中未定义,只是碰巧起作用了。

Operator precedence is irrelevant in this question. It's evaluation order that causes this behavior.

In C# i++ is evaluated before i % 2 since it's on the left side. Thus i % 2 is false and the right side of the if gets evaluated.

First you use precedence to get the syntax tree:

=
  buffer[i++]
  if i % 2
    then temp[end--]
    else temp[begin++]

On each node you evaluate the children from left to right. This implies that i++ is evaluated before i % 2.

Eric Lippert has plenty of posts on this, both here on SO, and on his blog:

Personally I'd avoid such code. It's much nicer to split it into multiple expressions, or even use a plain if statement instead of ? :


In C++ accessing a variable that was written to without a sequence point in between is undefined behavior. I think = is no sequence point, so I guess your expression is undefined in C++ and just happened to work.

相权↑美人 2024-12-24 06:38:25

我不知道,但你为什么不直接表明你的意图呢?

if(i % 2 == 0) {
    buffer[i] = temp[end--];
} else {
    buffer[i] = temp[begin++];
}

i++;

I don't know, but why don't you just make your intentions clear?

if(i % 2 == 0) {
    buffer[i] = temp[end--];
} else {
    buffer[i] = temp[begin++];
}

i++;
够运 2024-12-24 06:38:25

您确定 begin 吗?结束 是正确的吗?如果我没记错的话,最后你会错过一个元素。

以下是我在 C++ 中的编写方式:

for (; begin <= end; ++i)
{
    buffer[i] = temp[(i & 1) == 0 ? end-- : begin++];
}

但如果你仔细想想,循环内的条件实际上是不必要的,因为它会随着每次迭代而翻转。在循环内简单地进行两个复制操作会更有效:

while (begin < end)
{
    buffer[i++] = temp[end--];
    buffer[i++] = temp[begin++];
}
if (begin == end)
{
    buffer[i++] = temp[end--];
}

我将循环条件更改回 < 并添加了 if 以防出现奇数个元素。

Are you sure that begin < end is correct? You will miss one element at the end, if I'm not mistaken.

Here is how I would write it in C++:

for (; begin <= end; ++i)
{
    buffer[i] = temp[(i & 1) == 0 ? end-- : begin++];
}

But if you think about it, the conditional inside the loop really isn't necessary, because it flip-flops with every iteration. It would be more efficient to simply have two copy operations inside the loop:

while (begin < end)
{
    buffer[i++] = temp[end--];
    buffer[i++] = temp[begin++];
}
if (begin == end)
{
    buffer[i++] = temp[end--];
}

I changed the loop condition back to < and added an if in case there is an odd number of elements.

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