go笔记 (异或交换两个数字变量需要注意的问题)

一般可以用异或的方式不借助第三方值来交换数字,类似如下

func main() {
	swaps := func(k int, b int) (x, y int) {
		k ^= b
		b ^= k
		k ^= b
		return k, b
	}
	x,y :=swaps(5,6)
	fmt.Printf("结果为: %d,%d", x, y)
}
结果为: 6,5

 

但是今天在数组交换中装逼失败,比如如下输出的会是[0,3,1] ,而不是[1,3,1]

func main() {
	arr := [3]int{1,3,1}
	swaps := func(arr *[3]int,k int, b int) {
		arr[k] ^= arr[b]
		arr[b] ^= arr[k]
		arr[k] ^= arr[b]
	}
	swaps(&arr,0,0)
	fmt.Println(arr)
}

  

这是因为arr[k]和arr[b]索引相同时指向同一块内存。arr[k] ^ arr[b] 的结果则肯定为0,此时arr[k]也就是arr[b]都为0 ,后续的操作也就全部都是 0^0 结果自然为0.例如上面的交换数据函数改为同一块内存的两个参数值

func main() {
	swaps := func(k *int, b *int) (x, y int) {
		*k ^= *b
		*b ^= *k
		*k ^= *b
		return *k, *b
	}
	k := 5
	s := &k
	fmt.Printf("内存地址分别为: %p,%p 
", &k, s)
	x,y :=swaps(&k,s)
	fmt.Printf("结果为: %d,%d 
", x, y)

}
内存地址分别为: 0xc00000a0b8,0xc00000a0b8 
结果为: 0,0 

 

可以看到内存地址一致时会变为0

所以要用异或来交换两个值记得判断是否为同一块内存,例如在数组中就可以加上 索引k != b的判断,即如下即可

func main() {
	arr := [3]int{1,3,1}
	swaps := func(arr *[3]int,k int, b int) {
		if k != b {
			arr[k] ^= arr[b]
			arr[b] ^= arr[k]
			arr[k] ^= arr[b]
		}

	}
	swaps(&arr,0,0)
	fmt.Println(arr)
}

  

原文地址:https://www.cnblogs.com/hetutu-5238/p/12511913.html