zoukankan      html  css  js  c++  java
  • 为什么Swift和Python要抛弃++--?

    简单好用的++、--

    说到自增(++)自减(--)运算符,小伙伴们应该都不会陌生,在很多编程语言的代码中,都经常出现它们的身影。

    • 比如常用的for语句
    for (int i = 0; i < n; i++) {
        // TODO
    }
    
    • 比如经典的一行代码实现字符串拷贝
    // 将src的内容拷贝至dest
    void strcpy(char *dest, char *src) {
        while (*dest++ = *src++);
    }
    
    int main() {
        char s1[10], *s2 = "xmg_mj";
        strcpy(s1, s2);
        printf("%s", s1); // xmg_mj
        return 0;
    }
    

    使用得当的话,自增(++)自减(--)运算符的确可以让代码简洁又优雅。

    但是

    2大热门编程语言SwiftPython并不支持自增(++)、自减(--)运算符,这是为什么呢?

    这里先给出几个参考链接,有兴趣的小伙伴可以自行去阅读一下:

    这里只列出几个显而易见的理由

    • 有了强大又简洁的for-infor语句中可以完全不需要++、--
    // C++
    for (int i = 0; i < 5; i++) {
        cout << i << endl;
    }
    
    // Swift
    for i in 0..<5 {
        println(i)
    }
    
    // Python
    for i in range(5):
        print(i)
    
    • 尽管while (*d++ = *s++);看起来似乎简单而优雅,但对于初学者来说绝非简单,会增加学习成本。而SwiftPython更倾向于希望任何人都能快速上手这门编程语言。

    • 当混合使用前缀和后缀的++、--时

      • 会降低代码的可读性,比如while (n++ > --k),经验丰富的程序员也必须停下来思考一下代码的具体含义是什么
      • 运行结果可能会有不确定性

    运行结果的不确定性

    下面列出2段代码,变量b的结果是什么呢?(值得一提的是:实际开发中我们并不会这么写,这里把它列出来仅仅是为了讨论一些技术细节)

    int a, b;
    
    // 第1段代码
    a = 1;
    b = a++ + ++a + a++ + ++a;
    
    // 第2段代码
    a = 1;
    b = a++ + a++ + a++ + a++;
    

    实际上,上面的C语言代码在MSVC、MinGW编译器下得出的结果是不完全一致的

    • MSVC:微软出品
    • MinGW:GNU出品(可以理解为Windows版本的GCC)

    第1段代码

    结果一致,符合绝大部分人的预期,所以就不展开讨论了

    a = 1;
    b = a++ + ++a + a++ + ++a;
    // MSVC:b = 1 + 3 + 3 + 5 = 12
    // MinGW:b = 1 + 3 + 3 + 5 = 12
    

    第2段代码

    结果不一致

    • MSVC的结果是1 + 1 + 1 + 1 = 4
    • MinGW的结果是1 + 2 + 3 + 4 = 10
    a = 1;
    b = a++ + a++ + a++ + a++;
    // MSVC:b = 1 + 1 + 1 + 1 = 4
    // MinGW:b = 1 + 2 + 3 + 4 = 10
    

    你可能好奇:你怎么知道MinGW的计算过程是1 + 2 + 3 + 4呢?根据最终结果10反推回去猜出来的么?NO!如果是这样做的话,那就有点侮辱了程序员这个职业了。

    像这种不太容易从表面去理解的代码,你若想知道它的真正本质,那就要搬出强有力且精准的武器了,它就是汇编语言(Assembly Language)

    简单说明一下使用汇编语言的理由:

    • 众所周知,C语言代码最终都会被编译为机器语言代码(也叫做机器指令,只由0和1组成)
    • 那通过研究最终的机器指令来探索C语言代码的本质?由于机器指令极其晦涩难懂,因此,对一般人来说,这并不是一种高效的办法
    • 最佳的办法是:研究一下介于C语言机器语言之间的汇编语言代码
      • C语言汇编语言机器语言
      • 汇编语言代码比机器指令可读性高很多
      • 每一条机器指令都有与之对应的汇编语言代码
      • 因此,你研究汇编语言代码,基本就等同于研究机器指令,可读性+精准性兼具

    看看MSVC环境下的汇编代码

    • 红框代码:将4个a相加的结果赋值给b,由于a的初始值是1,所以b = 1 + 1 + 1 + 1 = 4
    • 绿框代码:让a执行4次自增1的操作,相当于执行4次a += 1

    看看MinGW环境下的汇编代码

    • 为了保证能基本看懂这段汇编代码,建议你可以理解为[rbp-0x4]代表变量a,[rbp-0x8]代表变量b
    • 绿框代码:让a执行自增1的操作,相当于执行a += 1
    • 红框代码:将a每次自增1之前的值累加起来,最后赋值给b
    • 可以看到,绿框、红框代码是交替执行的,所以最终b = 1 + 2 + 3 + 4 = 10

    最后2段代码

    最后再放2段代码出来,在MSVC和MinGW下的结果也是不一致的

    a = 1;
    b = ++a + ++a + ++a + ++a;
    // MSVC:b = 5 + 5 + 5 + 5 = 20
    // MinGW: b = 3 + 3 + 4 + 5 = 15
    
    a = 1;
    b = ++a + ++a + a++ + a++;
    // MSVC:b = 2 + 3 + 3 + 4 = 12
    // MinGW:b = 3 + 3 + 3 + 4 = 13
    

    根据前面的一些讲解,相信你现在可以推断出MSVC的结果了。

    但MinGW的结果可能还是会让人感觉到奇怪:它其实是先让最前面的2个++a执行a自增1的操作,后面的2个++aa++就照常处理,所以最终b = 3 + 3 + ...

    好了,就此打住,建议不要去纠结这些细节了,因为本来就不推荐这种写法。你只需要知道:多个前缀、后缀的自增自减一起使用时,结果具有不确定性。

    总的来说,++、--是把双刃剑,再者,它并非是编码过程中必不可缺的,所以被SwiftPython抛弃也是正常的事。

    关于汇编

    经常看到有人说:汇编语言都是上古时期的编程语言了,没啥用,甚至还有人说CC++这么古老的语言,没有任何学习价值。我个人并不赞同这些观点。掌握好汇编,可以更好地了解代码的本质,扫除一些基本的知识误区​。​

    因为时间和篇幅的关系,这篇文章并没有详细解释每一句汇编代码的作用。如果你对汇编感兴趣,可以参考以下图片

    之前有在B站上传一些汇编教程,有需要的小伙伴可以向公众号发送汇编两字,获取教程地址

    最后的思考题

    最后留一道思考题,可以将思考的结果直接留言评论

    不是说Python不支持自增(++)自减(--)运算符么,为什么下面的Python代码能运行成功呢?

    a = 10
    b = ++a
    
    c = a++ + ++a
    

    如果你特别希望我写点什么方面的内容,也可以留言建议,谢谢

    欢迎关注

  • 相关阅读:
    Windows JScript 在 游览器 中运行 调试 Shell 文件系统
    autohotkey 符号链接 软连接 symbolink
    软链接 硬链接 测试
    SolidWorks 修改 基准面 标准坐标系
    手机 路径 WebDAV 映射 驱动器
    Win10上手机路径
    explorer 命令行
    单位公司 网络 封锁 屏蔽 深信 AC
    cobbler自动化部署原理篇
    Docker四种网络模式
  • 原文地址:https://www.cnblogs.com/mjios/p/12674242.html
Copyright © 2011-2022 走看看