日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

go uintptr unsafe Pointer offset() 的使用

發布時間:2024/2/28 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 go uintptr unsafe Pointer offset() 的使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

go語言基本類型

類型名稱有無符號占用位數
int8Yes8
int16Yes16
int32Yes32
int64yes64
uint8No8
uint16No16
uint32No32
uint64No64
intYes32或64,等于cpu位數
uintNo32或64,等于cpu位數
runeNo32,與uint32等價
byteNo8,與uint8等價
uintptrNo64,與uint64等價

?

?

?

?

?

?

?

?

?

?

?

?

?

?

rune?類型是 Unicode 字符類型,和 uint32 類型等價,通常用于表示一個 Unicode 字符。rune 和 uint32 可以互換使用。

byte?類型與uint8類型等價,byte類型一般用于強調數值是一個原始的內存數據而不是 一個小的整數。

uintptr?是一種無符號的整數類型,與uint64等價,范圍:0 ~ 18446744073709551615,足以容納任何指針值轉換來的整型值。 uintptr類型只有在底層編程是才需要,特別是Go語言和C語言函數庫或操作系統接口相交互的地方。GC 不把 uintptr 當指針,uintptr 無法持有對象。uintptr 類型的目標會被回收,所以不要聲明uintptr類型的變量

不管它們的具體大小,int、uint和uintptr是不同類型的兄弟類型。其中int和int32也是 不同的類型, 即使int的大小也是32bit,在需要將int當作int32類型的地方需要一個顯式的類型轉換操作,反之亦然

unsafe.Pointer

一個可以指向任意類型的指針,不可以進行數值計算
有四種區別于其他類型的特殊操作:
1. 任意類型的指針值均可轉換為 Pointer
2. Pointer 均可轉換為任意類型的指針值
3. uintptr 均可轉換為 Pointer
4. Pointer 均可轉換為 uintptr

unsafe 庫讓 golang 可以像C語言一樣操作計算機內存,但這并不是golang推薦使用的,能不用盡量不用,就像它的名字所表達的一樣,它繞過了golang的內存安全原則,是不安全的,容易使你的程序出現莫名其妙的問題,不利于程序的擴展與維護

?

示例1(unsafe.Pointer用來取地址,uintptr用來取地址的10進制數值):

package main import ("fmt""unsafe" ) func main() {a := int(5)p := &afmt.Println("p:", p) // a的地址,16進制形式fmt.Println("unsafe.Pointer(&a):", unsafe.Pointer(&a)) // a的地址,16進制形式fmt.Println("uintptr(unsafe.Pointer(&a)):", uintptr(unsafe.Pointer(&a))) // a的地址,10進制形式 }

結果如下圖:

PS:每次運行a的地址可能是不同的,但?unsafe.Pointer(&a) 和?uintptr(unsafe.Pointer(&a))的值是一樣的,只是前者是指針類型,16進制,后者是整數類型,10進制,兩者相等,這里 0xc00000a0b8,轉換為10進制即 824633761976

示例2(地址計算,偏移,并修改)

package main import ("fmt""unsafe" ) func main() {a := [4]int{0, 1, 2, 3}p1 := unsafe.Pointer(&a[1]) // p1指向a[1]的起始地址// a[1]的地址類型轉換為uintptr類型,后移2個元素的位置,這樣移動到a[3]的起始地址位置p3 := unsafe.Pointer(uintptr(p1) + 2 * unsafe.Sizeof(a[0]))*(*int)(p3) = 6 // 先將Pointer類型轉換為*int類型,再賦值fmt.Println("a =", a) // 打印出來結果是:a = [0 1 2 6] }

結果如下圖:

PS:unsafe.Pointer 是橋梁,可以讓任意類型的指針實現相互轉換,也可以將任意類型的指針轉換為 uintptr 進行指針運

示例3(unsafe.Offsetof的使用)

該函數返回屬性x的起始地址和結構體起始地址的字節數

func Offsetof(x ArbitraryType) uintptr

代碼如下:

package main import ("fmt""unsafe" ) type Person struct {name stringage intgender bool } func main() {john := Person{"John", 30, true}pp := unsafe.Pointer(&john) // 結構體的起始地址pname := (*string)(unsafe.Pointer(uintptr(pp) + unsafe.Offsetof(john.name))) // 屬性name的起始地址,轉換為*string類型page := (*int)(unsafe.Pointer(uintptr(pp) + unsafe.Offsetof(john.age))) // 屬性age的起始地址,轉換為*int類型pgender := (*bool)(unsafe.Pointer(uintptr(pp) + unsafe.Offsetof(john.gender))) // 屬性gender的起始地址,轉換為*bool類型// 進行賦值*pname = "Alice"*page = 28*pgender = falsefmt.Println(john) // {Alice 28 false} }

實驗結果如下:

總結

以上是生活随笔為你收集整理的go uintptr unsafe Pointer offset() 的使用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。