Open3

C# pointer操作メモ

ピン留めされたアイテム
いぬいぬいぬいぬ

C#/C/C++/Rust/Go比較表

by ChatGPTくん

特性・操作項目 C# (unsafe) C# (ref/Span) C C++ Rust Go
ポインタ型の定義 int* p ref int, Span<int> int* p int* p, std::unique_ptr *const i32, *mut i32 *int
アドレス取得 int* p = &x ref int r = ref x int* p = &x int* p = &x let p = &x as *const i32 p := &x
参照/書き込み *p = 5, int v = *p r = 5, int v = r *p = 5, int v = *p *p = 5, int v = *p *p = 5, let v = *p (unsafe) *p = 5, v := *p
配列アクセス(スライス) *(p + i) span[i] p[i] p[i], std::span slice[i] slice[i]
NULL 許容 あり (null) ref, Span は非 null あり (NULL) あり (nullptr) あり (std::ptr::null()) あり (nil)
所有の概念 なし 借用に近い(Span等) なし unique_ptr/shared_ptr 明確な所有(例:Box<T> なし(GCによる管理)
借用(参照)管理 自己責任 ライフタイム制約あり なし 明示的に制御可能 借用チェッカーが管理 なし(制限なし)
ライフタイムの強制 なし ref struct, Span<T> なし std::span で制御可能 明示的に 'a で指定可能 なし
null 安全 なし あり(Spanなどは非null) なし なし Option<&T> などで安全に処理 なし
未初期化メモリへのアクセス 可(未定義動作) 不可(コンパイルエラー) 可(未定義動作) 可(未定義動作) unsafeでのみ可能
スライス表現 T* + length Span<T> T* + size_t std::span<T> &[T], &mut [T] []T
メモリの自動解放 なし(手動またはGC) GCで管理 なし(手動) RAII / smart pointer 所有者がdrop時に解放 GC による管理
スレッドセーフか? 非保証 条件付きで安全 非保証 条件付きで安全 Send, Sync によって制御 通常は安全(GC)
構文安全性レベル 低(unsafe) 高(ref/Span) 中〜高(スマートポインタ) 高(unsafe範囲のみ注意) 中(型安全 + GC)
代表的な用途 高速処理、interop stackalloc、構造体バッファ OS、デバイスレベル開発 システム、ゲームエンジン 高速・安全なシステム開発 Web、サーバー処理
junerjuner

C# の Span<T> の アドレス取得だと インデクサが ref 戻り値なのでそこから取れますね。

using System;
Span<int> span = [1,2,3,4];
Console.WriteLine($"before:[{string.Join(", ",span.ToArray())}]");
ref int num = ref span[0];
num = 6;
Console.WriteLine($"after :[{string.Join(", ",span.ToArray())}]");

https://sharplab.io/#v2:C4LgTgrgdgPgAgJgIwFgBQBlADgQygHgEspgA+AAgGdcpyBecgbSQBoEWBmFgFgF0BudHCQBOABQASAEQAjAKYAzAPZg5IRgG9hABgB0AKSXExUluVPU8ugCpKAgmDA4AnmICUbgL68pbwWlUFcmJgcigIAFt6ckCqGkZtAXRwqIYANn9hcWkcBWA5MHJ1LSQ9Q2NTcxZLKBt7Rxd3Lx8/IA

いぬいぬいぬいぬ

C言語とC#におけるメモリ・ポインタ操作対応表

by ChatGPTくん

No 操作内容 Cコード例 C# unsafe例 C# managed例
1 アドレス取得 int* p = &x; int* p = &x; ref int r = ref x;
2 間接参照で代入 *p = 10; *p = 10; r = 10;
3 間接参照で読み取り int y = *p; int y = *p; int y = r;
4 ポインタ関数引数 void f(int* p) void F(int* p) void F(ref int x)
5 配列要素アクセス *(arr + i) *(arr + i) ref int r = ref arr[i];
6 2次元配列的アクセス *(*(mat + i) + j) *(mat + i * cols + j) ref int r = ref mat[i * cols + j];
7 ポインタインクリメント p++; p++; index++; ref int r = ref arr[index];
8 構造体フィールドアクセス p->x = 5; p->x = 5; ref var r = ref point; r.X = 5;
9 ポインタ比較 if (p1 < p2) if (p1 < p2) if (index1 < index2)
10 メモリコピー memcpy(dst, src, n); Buffer.MemoryCopy(src, dst, n, n); src[..n].CopyTo(dst);
11 一時メモリ確保(stack) int tmp[10]; int* tmp = stackalloc int[10]; Span<int> tmp = stackalloc int[10];
12 calloc int* p = calloc(10, sizeof(int)); NativeMemory.AllocZeroed(...) new int[10];
13 realloc realloc(p, new_size); NativeMemory.Realloc(...) Array.Resize(...)
14 free free(p); NativeMemory.Free(...) // GC任せ
15 ダブルポインタ int** pp = &p; int** pp = &p; // ref ref unsupported, 関数経由で代替
16 文字列コピー strcpy(dst, src); Encoding.ASCII.GetBytes(...) src.AsSpan().CopyTo(dst);