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、サーバー処理 |
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())}]");

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); |