交换两个数字golang

Nav*_*han 12 go

我想了解go的内部.请考虑以下代码

a,b := 10,5
b,a = a,b
Run Code Online (Sandbox Code Playgroud)

上面的代码完美地交换2个数字,a变为5,b变为10.我无法理解这是如何工作的.考虑到第二行代码,如果a首先被分配给b,那么b将是10.现在,如果我们将b分配给a,那么不应该是10.

请帮我理解这是如何工作的

谢谢

cat*_*cat 24

TL; DR:反汇编表明CPU必须足够聪明才能看到发生了什么,并使用寄存器来避免覆盖内存中的现有值.


这个问题让我对Golang有了更多的了解,谢谢!

为了弄清楚编译器如何生成本机代码,我们需要查看它生成的汇编代码,它由链接器转换为机器代码.

我写了一个Go程序来帮助解决这个问题:

package main

import "fmt"

func main() {
    fmt.Println(myfunction())
}

func myfunction() []int {
    a, b := 10, 5
    b, a = a, b
    return []int{a, b}
}
Run Code Online (Sandbox Code Playgroud)

使用go tool compile -S > swap.s,我然后CTRL - F'为myfunction(这是该名称的点:易于搜索),并找到这四行,对应myfunction于Go代码中的前两行:(注意这是我的64位机器;其他架构如32位的输出会有所不同)

0x0028 00040 (swap.go:10)   MOVQ    $10, CX         ; var a = 10
0x002f 00047 (swap.go:10)   MOVQ    $5, AX          ; var b = 5
0x0036 00054 (swap.go:11)   MOVQ    CX, "".b+16(SP) ; copy a to *b+16
0x003b 00059 (swap.go:11)   MOVQ    AX, "".a+24(SP) ; copy b to *a+24 
Run Code Online (Sandbox Code Playgroud)

Go的反汇编对调试很有帮助:D

查看asm的Golang文档,我们可以看到汇编程序使用间接来处理值.

当程序运行时,CPU足够聪明,可以看到发生了什么,并使用寄存器来避免覆盖现有值.

如果您有兴趣,这是完整的反汇编.

  • C 是否也能做到这一点?通过与机器码不同的高级抽象,Golang 能够指示 CPU 一次读取两个或多个值/变量。 (2认同)
  • CPU 根本不存在智能!CPU 没有提示不要覆盖值,并且它会很乐意这样做。第一次写入将在 uop 生成期间被消除,或者将被融合到宏 uop 中。除了 uarch 问题之外,这里发生的是编译器生成代码,以便将交换的值直接分配给返回元组。编译器可以这样做,因为交换是在函数内完成的。如果您在单独的函数中执行交换操作,您将看到编译器将使用额外的临时寄存器。 (2认同)