diff --git a/examples/basic/unsafes/README.md b/examples/basic/unsafes/README.md index c23be6f0..1069a708 100644 --- a/examples/basic/unsafes/README.md +++ b/examples/basic/unsafes/README.md @@ -2,8 +2,9 @@ このディレクトリには以下のサンプルがあります。 -| file | example name | note | -| -------------------- | ----------------- | --------------------------------------- | -| unsafe_sizeof.go | unsafe_sizeof | unsafe.Sizeof() についてのサンプルです. | -| unsafe_string.go | unsafe_string | unsafe.String() のサンプルです. | -| unsafe_stringdata.go | unsafe_stringdata | unsafe.StringData() のサンプルです. | +| file | example name | note | +| ---------------------- | ------------------- | -------------------------------------------------------------------- | +| unsafe_sizeof.go | unsafe_sizeof | unsafe.Sizeof() についてのサンプルです. | +| unsafe_string.go | unsafe_string | unsafe.String() のサンプルです. | +| unsafe_stringdata.go | unsafe_stringdata | unsafe.StringData() のサンプルです. | +| unsafe_pointer_cast.go | unsafe_pointer_cast | unsafeパッケージを用いてポインタを任意の型にキャストするサンプルです | diff --git a/examples/basic/unsafes/examples.go b/examples/basic/unsafes/examples.go index c4a7ea30..8b19ec0a 100644 --- a/examples/basic/unsafes/examples.go +++ b/examples/basic/unsafes/examples.go @@ -16,4 +16,5 @@ func (r *register) Regist(m mapping.ExampleMapping) { m["unsafe_sizeof"] = Sizeof m["unsafe_string"] = UnsafeString m["unsafe_stringdata"] = UnsafeStringData + m["unsafe_pointer_cast"] = PointerCast } diff --git a/examples/basic/unsafes/unsafe_pointer_cast.go b/examples/basic/unsafes/unsafe_pointer_cast.go new file mode 100644 index 00000000..e43e6d9b --- /dev/null +++ b/examples/basic/unsafes/unsafe_pointer_cast.go @@ -0,0 +1,46 @@ +package unsafes + +import ( + "fmt" + "unsafe" +) + +// PointerCast は、unsafeパッケージを用いてポインタを任意の型にキャストするサンプルです。 +// +// unsafe.Pointer は、C言語でいう (void *) と同じものとなる。 +// C言語において、(void *) は何にでも成れるのと同様に unsafe.Pointer はGoでもどの型にもキャスト出来る。 +// ただし、unsafeパッケージを利用する時点でGoの持つ安全性を無くすことに注意が必要。 +// +// REFERENCES: +// - https://pkg.go.dev/unsafe@go1.25.3#Pointer +func PointerCast() error { + var ( + value int = 0x01020304 + ptr unsafe.Pointer + cast1 *byte + cast2 *[4]byte + ) + // 元の値をunsafe.Pointerにする + ptr = unsafe.Pointer(&value) + + // C言語でいう (char *)ptr; のような変換 + cast1 = (*byte)(ptr) + + // 明示的な配列のポインタへの変換 + cast2 = (*[4]byte)(ptr) + + // 値を確認 (cast1) + // *cast1 は最初の1バイトのみを参照する (リトルエンディアン環境では 0x04) + // 後続バイトにアクセスするには unsafe.Add() または uintptrを使ったポインタ演算 などを使用する必要がある + fmt.Printf("cast1: 1バイト目: 0x%02X\n", *cast1) + fmt.Println("---------------------------------") + + // 値を確認 (cast2) + // *[4]byte 型なので配列として全4バイトに直接アクセス可能 + // メモリレイアウトはエンディアンに依存する(リトルエンディアンでは逆順) + for i, v := range cast2 { + fmt.Printf("cast2: %dバイト目: 0x%02X\n", i, v) + } + + return nil +}