實現golang中memset函數

C語言中的memset

在C/C++中,有一個memset函數,常常用來清空一段內存。

#include <string.h>
// 將s的前n個字節用c填充
void *memset(void *s, int c, size_t n);

// 用法舉例
int arr[100];
// 將數組內存全部置爲0
memset(&arr, 0, sizeof(arr));

由於是s是void* 類型的指針,那麼任何類型的內存都可以清空。但是在golang中,類型檢查特別嚴格,並沒有提供類似的函數。

Golang中一種實現

// 可以填充數組、結構體
func MemSet(s unsafe.Pointer, c byte, n uintptr) {
	ptr := uintptr(s)
	var i uintptr
	for i = 0; i < n; i++ {
		pByte := (*byte)(unsafe.Pointer(ptr + i))
		*pByte = c
	}
}

func main() {
	var arr [10]int32
	MemSet(unsafe.Pointer(&arr), 1, unsafe.Sizeof(arr))
	fmt.Printf("%+v\n", arr)

	MemSet(unsafe.Pointer(&arr), 0, unsafe.Sizeof(arr))
	fmt.Printf("%+v\n", arr)
}
// 輸出:
[KentZhang@LOCAL-192-168-97-2]$ go run memset.go
[16843009 16843009 16843009 16843009 16843009 16843009 16843009 16843009 16843009 16843009]
[0 0 0 0 0 0 0 0 0 0]

三點說明:

  1. unsafe.Pointer 是一種通用的指針類型,可以將任何數據類型的指針轉化爲 unsafe.Pointer,相當於C語言中的void*指針。
  2. unsafe.Pointer不能進行計算,即指針不能加減偏移計算,所以還必須轉化爲uintptr類型,uintptr本質上是一個整數,於是就可以計算了。
  3. uintptr是整數,不是指針,無法進行取值賦值運算,還要轉化爲unsafe.Pointer,再轉爲對應類型的指針。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章