2014-01-19 57 views
1

在我的Go程序中,我正在调用C函数,我可以成功地从int转换为ptrdiff_t。 (即使Go类型对于任何现代体系结构都太小,甚至int8也会成功编译)。但*int*ptrdiff_t会产生编译器错误:cannot convert <varname> (type *int) to type *_Ctype_ptrdiff_t。唯一允许编译成功的类型是int64。我意识到我可以将我的变量声明为(*)C.ptrdiff_t,但我想了解相应的Go类型以及Go编译器在此实例中的意外行为?转换为* ptrdiff_t的转换类型?

回答

2

ptrdiff_t是特定大小的整数类型。当您将另一个整数类型转换为ptrdiff_t时,编译器重新调整整数大小。换句话说,它会更改旧整数的内存表示以匹配新类型。然后将这个新的表示放在内存中的不同位置。

指针是内存中的一个位置。因此,只能将其转换为指向相同内存布局的类型。 int64与ptrdiff_t具有相同的大小,因此内存表示形式相同,指针可以自由转换。

如果您希望转换任意整数类型,您需要首先更改它的内存表示形式,并通过将其分配给一个变量并获取其指针,为其指定一个新的位置。

newtype := ptrdiff_t(oldInt) 
pnewtype := &newtype 
+0

啊哈,我遗漏的一块是一个int8将被扩展到适当的大小。据推测,如果我在ptrdiff_t为32位的环境下编译,那么使用int64会触发警告或错误。这导致我相信使用* int64作为等同于* ptrdiff_t的Go仅适用于64位版本。有没有一种体系结构不可知的Go类型可以工作?我试过uintptr,因为它的大小保证了一个指针(因此应该适合于保持指针之间的差异),但Go不允许转换。 – errcw

+0

@errcw,在Go中,将指针转换为具体类型的实例为uintptr,必须首先将其转换为unsafe.Pointer,这样才能正常工作:x:= X {}; var p uintptr = uintptr(unsafe.Pointer(&x))' – kostix

+0

够公平的,但这仍然让我想知道什么是正确的体系结构不可知的Go类型映射到* C.ptrdiff_t。 – errcw