"C语言中为什么代码'A = A + B - (B = A)'可以交换变量A和B的值?"

5

要交换整数 A 和 B,在 C 中似乎可以使用以下代码:

A = A + B - ( B = A);

为什么这个能够起作用呢?如果在所有情况下都行得通,那么这个方法是否可以用来简化其他常见的算法呢?

3
这段代码在很多实现上可能会起作用,但是根据标准规定,它的行为是未定义的。 - Marian
4
此外,它仅仅是将临时变量隐藏在B=A 的部分中,并没有真正简化任何东西。我认为它会降低代码的可读性。 - D.R.
1
有趣的标题,因为它暗示着处理A、B和C。 - meaning-matters
常规的做法是:A = A + B; B = A - B; A = A - B; 或者 A = A ^ B; B = A ^ B; A = A ^ B; 在旧的双累加器计算机上,这样可以避免使用内存位置来保存临时值。 - rcgldr
3个回答

6

根据标准,实际上这会引起未定义的行为-

C99 §6.5:“2. 在前一个和下一个序列点之间,一个对象通过对表达式的求值最多只能修改其存储的值一次。此外,先前的值只能读取以确定要存储的值。”


2
不应该依赖这样的代码工作,因为它依赖于从左到右进行处理的事实。任何不这样做的实现都会导致其失败。应该避免编写在所有平台和编译器上均无法正常工作或依赖于未记录或未明确定义事物的代码。
为什么从左到右时它能够工作: 假设A = 1且B = 3 A = A + B - ( B = A); A = 1 + 3 - (1) = 3 B的分配发生在i离开()的地方 底线是只有在从左到右处理时,B对A的分配才会晚一些。
当从右到左处理相同的示例时: A = A + B - ( B = A); A = 1 + 1 - (1) = 1 现在B的分配首先发生。
再次强调,不应该依赖于读者无法理解正在发生什么以及编译器相关的代码,而在此处情况就是如此。

1

这只是相对于标准/显而易见的方法来说,使用了更少的行数/分号。

  • 它引入了额外的操作,可能会使编译器无法进行优化
  • 降低了可读性(正如D.R.所提到的)
  • 滥用非标准行为(正如Marion所提到的),这可能会导致它在某些编译器上失败

你永远不应该使用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接