为什么结构体数组比较会产生不相等的结果
在 Go 中,比较空结构体数组可能会产生意想不到的结果。这种行为源于语言中指针和零大小变量的微妙本质。
指向零大小变量的指针
根据 Go 规范,指向不同的零大小变量不一定具有唯一的地址。这是因为编译器可能会优化零大小的变量,从而导致不可预测的内存分配。
示例
考虑以下代码:
var s, ss struct{} // two empty structs arr1 := [6]*struct{}{&s} // array with empty struct pointer arr2 := [6]*struct{}{&ss} // array with empty struct pointer fmt.Println(&s == &ss, arr1 == arr2) // false, true
在此示例中,arr1 和 arr2 是两个数组,其中包含指向不同空结构 s 和 ss 的指针。令人惊讶的是,比较 arr1 == arr2 返回 true。这是因为编译器可能将 s 和 ss 放置在同一地址,尽管它们具有不同的标识。然而, &s == &ss 的计算结果为 false,因为它直接比较指针本身。
结构中的 Int 变量
但是,当非零值存储在结构体,例如整数,比较行为会发生变化。
var l, ll struct{A int}{} arr3 := [6]*struct{A int}{&l} // array with empty struct pointer arr4 := [6]*struct{A int}{&ll} // array with empty struct pointer fmt.Println(&l == &ll, arr3 == arr4) // false, false
在这种情况下,比较arr3 和 arr4 返回 false,表明数组不相等。这是因为结构中存储的非零整数为它们提供了不同的地址。
逃逸分析和变量重定位
意外行为也可能受到逃逸分析的影响,一种编译器优化,确定变量是否需要在堆上或堆栈上分配。如果一个变量逃逸了它的局部作用域,它将被分配在堆上以确保它在程序的其他部分中的可访问性。
对于指向空结构的指针,如果它们逃逸,编译器可能会将它们重新定位到不同的堆地址。此重定位影响了它们的相等性比较,导致错误。
以上是为什么 Go 中空结构的数组比较有时会产生意外结果?的详细内容。更多信息请关注PHP中文网其他相关文章!