在不使用C中的第三个变量的情况下交换两个变量的值?

时间:2014-07-17 20:12:07

标签: c expression operator-precedence sequence-points

我找到了以下代码段:

#include <stdio.h>

int main(void) {
    int x=10,y=15;
    x=x+y-(y=x);
    printf("x=%d y=%d",x,y);
    return 0;
}
  

它实际上交换了变量

有人可以解释一下代码如何交换变量吗?

我认为括号首先执行然后表达式导致

x=x+y-y;

3 个答案:

答案 0 :(得分:6)

此算法不起作用,因为它在此行上调用未定义的行为:

x=x+y-(y=x);
    ^  ^

您正在修改y,并根据C99标准草案的6.5部分在同一序列点中使用其值:

  

在前一个和下一个序列点之间,一个对象应该具有它   通过评估一次最多修改一次的储值   表达式.72)此外,先验值只能读取   确定要存储的值.73)

由于未明确说明子表达式的评估顺序,因此还存在未指明行为的问题:

  

运算符和操作数的分组由语法表示.74)   除非后面指定(对于函数调用(),&amp;&amp;,||,?:和   逗号运算符),子表达式的评估顺序和   发生副作用的顺序都是未指明的。

在这种情况下,如果您使用clang,则会提供以下警告:

warning: unsequenced modification and access to 'y' [-Wunsequenced]
x=x+y-(y=x);
    ~   ^

默认情况下,我可以告诉你。您可以使用gcc-Wall收到类似的警告。

有几个SO问题涉及如何在没有临时的情况下进行交换,例如Swapping two variable value without using 3rd variable

答案 1 :(得分:2)

这实际上是未定义行为的结果,因为有一些叫做序列点的东西。基本上,在这种情况下,C标准不要求在评估表达式期间以任何顺序存储值。事实上,以下内容肯定是可能的:

  1. 评估y = x,并将值存储在y中。在这种情况下,x仍然是10,y现在也是10.表达式本身的计算结果为10(赋值的左侧)。
  2. 评估x = x + y - (y = x),相当于x = x + y - 10xy均为10,因此x = 10 + 10 - 10x,因此x现为10。
  3. 现在,yy = x都是10,原始值15现在已丢失。

    编辑:至于如何交换的方式,可能是由于优化:

    1. 评估y,但不要将值存储在y中。 x = x + y - 10然后仍然保持值15,而赋值表达式的计算结果为10.
    2. 现在,x = 10 + 15 - 10评估为{{1}},产生正确的值。
    3. 两种情况都有效,但会产生不同的结果。

答案 2 :(得分:2)

  

我认为括号会先执行......

这是一个无效的假设。括号会影响表达式中运算符的优先级。它们没有指定执行顺序。在

 a = b + c + (d * e);

很可能b + c(d * e)之前计算出来。或者它可能不会。 C语言标准保留了子表达式未指定的评估顺序。您发布的代码会调用未定义的行为,因为y在没有插入序列点的情况下被读取和写入。再次注意,括号不会引入序列点(分号可以)。