【问题标题】:Swap trick: a=b+(b=a)*0;交换技巧:a=b+(b=a)*0;
【发布时间】:2011-08-05 01:36:41
【问题描述】:
a=b+(b=a)*0;

这句话可以交换a和b的值。
我已经用 C# 试过了,它可以工作。
但我只是不知道它是如何工作的。
例如

a = 1, b = 2

我列出了它的步骤如下:

b = a -> a = 1, b = 1
b * 0 -> a = 1, b = 1
b + 0 -> a = 1, b = 1
a = b -> a = 1, b = 1 ?

但是 b 的值可能是错误的。
有人可以帮我吗?这让我很困惑。

【问题讨论】:

  • 有趣!直到! :D 投赞成票!从来不知道这个技巧,但如果我在生产中看到它,我会让那个编码器在 200x 386-16Mhz 机器上安装 Windows ME...直到他求饶:)
  • @cindy 我选择这个问题来发布我的投诉。这个网站上的每个人都在抱怨,撕毁,并对任何发布的内容投反对票。请参阅下面的答案和 cmets。在你的情况下,我首先看到了混乱。直到,我看到了作业。我的意思是,在行尾的快速评论将有助于“交换 A 和 B”。无论如何,这个网站让我很生气。我们来到这里,提出问题并获得帮助。你只是问,这是如何工作的,而不是消极的。我是否发表了负面评论,是的,我猜是的。

标签: c# swap


【解决方案1】:
a=b+(b=a)*0;

中间的(b=a)是一个赋值语句,将b设置为a的当前值,副作用是它的结果是b的(最终值)。当它乘以 0 时,你得到 0,但分配仍然发生。

外部位将a 设置为b 加上(b=a)*0 的结果(为零)。因为原来的b(b=a)位赋值之前已经被用来开始设置a,所以赋值对a没有影响。换句话说,它是一个原子a = b; b = a;,交换了两个值。

C# 以严格的从左到右的顺序评估事物(与 C 和 C++ 不同)以避免一大类细微的错误。请注意,编译器可以以不同的顺序评估它们,但前提是它可以确定它没有效果(这里不是这种情况)。

您发布的 sn-p 有效,但也很丑陋,不是一个好主意,尤其是当您可以使用更具可读性的时候:

int t = a; a = b; b = t;

您在此处看到的技巧、XOR 交换技巧以及 Duff 的设备在体面的、可维护的代码中没有位置。它们通常是编码人员展示他们有多聪明的一种方式,但它们通常只是展示他们是多么糟糕

如果您在生产代码中看到过类似的情况,我认为世界上没有任何陪审团会因为您追捕肇事者并用汇总的程序清单将他们殴打致死而定罪。

你应该编写你的代码,就好像下一个必须维护它的人是一个知道你住在哪里的精神病患者——在我的情况下,你有一半是对的——我不知道你住在哪里:-)

【讨论】:

  • 你确定首先计算b 是在before 赋值运算符之前完成的吗? C#真的保证+运算符的运算顺序吗?
  • @Ivan,它肯定是从左到右的(除非编译器可以确定它没有区别,但它确实在这里):msdn.microsoft.com/en-us/library/Aa691322。他们试图专门避免 C/C++ 重新排序评估中的大量问题。
  • 感谢您的明确答复。关于编码风格,我完全同意你的看法。关键是可维护的。但是,当我遇到这样的伎俩时,我想在吐之前了解它。顺便说一句,这是我的第一个问题,你给我一个好的开始。我觉得很开心:)
  • 应该非常小心地使用类似这个问题的技巧,尤其是当您不熟悉语言标准如何定义细节时。也不鼓励在软件开发中使用这些技巧。无论如何思考和探索这些技巧有助于理解特定的编译器。例如,这个问题中的技巧在 gcc/g++ 中不起作用。
  • 我很喜欢答案的最后一段,尤其是精神病患者的用词。
【解决方案2】:

啊!你在哪里看到的??我已经习惯了 (a ^= b; b ^= a; a ^= b;) 把戏,所以我至少认出了它(不要开枪!我从来没有说过我使用它!),但我'd 不得不看那个一分钟......如果你在生产代码中看到它,请找出是谁写的并伤害了他。

正如其他人所说(但我想强调一下):“a = b”是一个赋值,但它也是一个有值的表达式。这就是为什么你可以做“a = b = c = d”之类的事情——这不是一种特殊的语言技巧;它们只是分组为“a = (b = (c = d))”,而“d”的值将折回所有这些变量。

【讨论】:

    【解决方案3】:
    0. a=b+(b=a)*0 | | a = 1, b = 2 1. 评估 b | a=2+(b=a)*0 | a = 1, b = 2 2. 评估 (b=a) | a=2+1*0 | a = 1, b = 1 3. 评估 1*0 | a=2+0 | a = 1, b = 1 4. 评估 2+0 | a=2 | a = 1, b = 1 5. 评估 a=2 | | a = 2, b = 1

    【讨论】:

      猜你喜欢
      • 2017-01-21
      • 2021-09-10
      • 1970-01-01
      • 2015-03-20
      • 2021-11-28
      • 1970-01-01
      • 2014-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多