• c# 连等算式都在做什么


    在研究两个整数互换的方法时(详细看这里),发现了一个有趣的现象。

    a ^= b ^= a ^= b;      a ^= b;b ^= a;a ^= b;

    有兴趣的童鞋可以看看下面代码的结果是什么:

    int a = 10;
    int b = 5;
    a ^= b ^= a ^= b;
    Console.WriteLine("{0}  {1}", a, b);

    一直以为a=b=c就是按照先后顺序执行b=c,a=b。照上面的执行结果来看,还不一定。

    到底执行的顺序怎么样,要看看反编译的代码才知道。

    先看看a=b=c=30都在做什么:

    IL_0008:  ldc.i4.s   30 //推送30到栈顶端
    IL_000a:  dup           //复制一个30到栈顶端
    IL_000b:  stloc.2       //提取顶端的30赋值给索引为2的变量,也就是c
    IL_000c:  dup           //复制一个栈顶端的30
    IL_000d:  stloc.1       //提取顶端的30赋值给索引为1的变量,也就是b
    IL_000e:  stloc.0       //提取顶端的30赋值给索引为0的变量,也就是a

    这样来看,a=b=c=30可以理解成c=30,b=30,a=30.

    再看看a ^= b ^= a ^= b在做什么(初始化这里a=10,b=5):

    IL_0006:  ldloc.0 //推送索引为0的变量值到栈顶端,也就是10
    IL_0007:  ldloc.1 //推送5
    IL_0008:  ldloc.0 //推送10 
    IL_0009:  ldloc.1 //推送5
    IL_000a:  xor     //提取10和5,做异或运算,将结果15推送到栈顶端 
    IL_000b:  dup     //复制15
    IL_000c:  stloc.0 //提取15赋值给a
    IL_000d:  xor     //取顶端的两个值15和5,做异或运算,将结果10推送到栈顶端
    IL_000e:  dup     //复制10
    IL_000f:  stloc.1 //提取10赋值给b
    IL_0010:  xor     //取顶端的两个值10和10做异或运算,结果0放到栈顶端
    IL_0011:  stloc.0 //提取0赋值给a

    做图解如下(作图水平不高,但应该勉强能看懂):

    整个过程,用代码还原就是

        a1=a0^b0=15;

    然后  b1=b0^a1=10;

    再然后 a2=a0^b1=10^10=0。

    前面两步的环节基本上是我们想要的,但是第三步a2=a0^b1却脱离了我们的原意,这里采用了a0做异或而不是a1,所以对应的结果也就出现了偏差。

    因此,这一行代码执行下来,a=0,b=10,结果显然并不是我们想要的。

    接下来,再看看a ^= b;b ^= a;a ^= b;在干嘛:

    IL_0006:  ldloc.0  //推送10
    IL_0007:  ldloc.1  //推送5
    IL_0008:  xor      //提取10和5做异或运算,得15,推送至栈顶
    IL_0009:  stloc.0  //将15赋值给a
    IL_000a:  ldloc.1  //推送b的值5
    IL_000b:  ldloc.0  //推送a的新值15
    IL_000c:  xor      //提取15和5做异或运算,得10,推送至栈顶
    IL_000d:  stloc.1  //将10赋值给b
    IL_000e:  ldloc.0  //推送a的值15
    IL_000f:  ldloc.1  //推送b的新值10
    IL_0010:  xor      //提取15和10做异或运算,得5,推送至栈顶
    IL_0011:  stloc.0  //将5赋值给a

    整个过程比较清晰。中规中矩的异或计算然后赋值,再异或,再赋值,再异或赋值。最后a=5,b=10,结果和我们想的一样。

    C#里面可以写连等句式,但是其中的逻辑一定要小心,尤其是连等过程中有变量赋值的,更要注意。平时使用的时候,建议不要为了省那两行的代码量而用连等语句拼凑,因为运算的结果可能和我们想要的不一样,而导致程序bug,得不偿失。 

  • 相关阅读:
    css3圆环百分比,菜单栏定位导航
    Css中的两个重要概念:块状元素和内联元素
    前端进阶试题(css部分)
    HTML5移动开发学习笔记之CSS3基础学习
    HTML5移动开发学习笔记之Canvas基础
    js加载从0到80变化过程代码,让其4s中加载完毕
    我了解到的JavaScript异步编程
    原生JS+Canvas实现五子棋游戏
    Web缓存相关知识整理
    百度前端技术学院2017学习总结
  • 原文地址:https://www.cnblogs.com/icyJ/p/Multi_Equal.html
Copyright © 2020-2023  润新知