第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

Go:如何將 unsafe.Pointer 轉(zhuǎn)換為指向長度未知的數(shù)組的指針?

Go:如何將 unsafe.Pointer 轉(zhuǎn)換為指向長度未知的數(shù)組的指針?

阿晨1998 2022-03-07 15:53:37
我正在嘗試編寫一個(gè) Go 程序,該程序用于將mmap包含float32值的非常大的文件映射到內(nèi)存中。這是我的嘗試(受先前答案的啟發(fā),為簡潔起見省略了錯(cuò)誤處理):package mainimport (    "fmt"    "os"    "syscall"    "unsafe")func main() {    fileName := "test.dat"    info, _ := os.Stat(fileName)    fileSize := info.Size()    n := int(fileSize / 4)    mapFile, _ := os.Open(fileName)    defer mapFile.Close()    mmap, _ := syscall.Mmap(int(mapFile.Fd()), 0, int(fileSize),        syscall.PROT_READ, syscall.MAP_SHARED)    defer syscall.Munmap(mmap)    mapArray := (*[n]float32)(unsafe.Pointer(&mmap[0]))    for i := 0; i < n; i++ {        fmt.Println(mapArray[i])    }}這失敗并顯示以下錯(cuò)誤消息:./main.go:21: non-constant array bound n由于n由文件的長度決定(在編譯時(shí)未知),因此我無法用強(qiáng)制轉(zhuǎn)換n中的常量值替換。如何轉(zhuǎn)換mmap為float32值的數(shù)組(或切片)?
查看完整描述

2 回答

?
慕斯王

TA貢獻(xiàn)1864條經(jīng)驗(yàn) 獲得超2個(gè)贊

您首先轉(zhuǎn)換為具有可以適合您的數(shù)據(jù)的靜態(tài)長度的類型的數(shù)組,然后將該數(shù)組切片為正確的長度和容量。

mapSlice := (*[1 << 30]float32)(unsafe.Pointer(&mmap[0]))[:n:n]


查看完整回答
反對(duì) 回復(fù) 2022-03-07
?
繁星coding

TA貢獻(xiàn)1797條經(jīng)驗(yàn) 獲得超4個(gè)贊

不幸的是,在您的情況下,您無法獲得指向數(shù)組的指針。這是因?yàn)閚它不是一個(gè)常數(shù)值(即它是在運(yùn)行時(shí)用 確定的fileSize/4)。(注意如果fileSize是常數(shù),你可以得到一個(gè)數(shù)組。)


雖然有安全和不安全的選擇。


安全的,或者有些人可能稱之為“正確”的方式——這需要一個(gè)副本,但你可以控制字節(jié)序。這是一個(gè)例子:


import (

    "encoding/binary"

    "bytes"

    "unsafe" // optional

)


const SIZE_FLOAT32 = unsafe.Sizeof(float32(0)) // or 4


bufRdr := bytes.NewReader(mmap)

mapSlice := make([]float32, len(mmap)/SIZE_FLOAT32) // = fileSize/4

err := binary.Read(bufRdr, binary.LittleEndian, mapSlice) // could pass &mapSlice instead of mapSlice: same result.

// mapSlice now can be used like the mapArray you wanted.

有幾種方法可以不安全地做到這一點(diǎn),但在 Go 1.17 中它非常簡單。


mapSlice := unsafe.Slice((*float32)(unsafe.Pointer(&mmap[0])), len(mmap)/SIZE_FLOAT32)

你也可以使用reflect.SliceHeader. 為了防止垃圾收集器問題,這里有很多細(xì)微差別需要注意:


var mapSlice []float32 // mapSlice := []float32{} also works (important thing is that len and cap are 0)


// newSh and oldSh are here for readability (i.e. inlining these variables is ok, but makes things less readable IMO)

newSh := (*reflect.SliceHeader)(unsafe.Pointer(&mapSlice))

oldSh := (*reflect.SliceHeader)(unsafe.Pointer(&mmap))


// Note: order of assigning Data, Cap, Len is important (due to GC)

newSh.Data = oldSh.Data

newSh.Cap = oldSh.Cap/SIZE_FLOAT32

newSh.Len = oldSh.Len/SIZE_FLOAT32


runtime.KeepAlive(mmap) // ensure `mmap` is not freed up until this point.

unsafe@JimB 的回答中給出了我能想到的最后一種方法——將 anmmap轉(zhuǎn)換為Dataan unsafe.Pointer,然后將其轉(zhuǎn)換為一個(gè)任意大的指向數(shù)組的指針,最后將該數(shù)組切片指定為所需的大小和容量。


查看完整回答
反對(duì) 回復(fù) 2022-03-07
  • 2 回答
  • 0 關(guān)注
  • 211 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)