2014-01-19 85 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