C# Unsafe类的用法 - 在C#中进行指针操作

来源:这里教程网 时间:2026-02-21 17:35:10 作者:

Unsafe 类本身并不存在于 C# 标准库中。这是一个常见误解。C# 中没有名为

Unsafe
的类来“封装”指针操作。真正支持指针和底层内存操作的是 unsafe 上下文(unsafe context),配合
fixed
stackalloc
、指针类型(如
int*
)以及
System.Runtime.CompilerServices.Unsafe
这个静态类(需引用
System.Runtime.CompilerServices.Unsafe
NuGet 包)。

unsafe 上下文:开启指针操作的前提

要在 C# 中使用指针,必须将代码标记为

unsafe
,并在编译时启用不安全代码支持(项目文件中设置
<allowunsafeblocks>true</allowunsafeblocks>
或命令行加
/unsafe
)。

可在方法、类型或代码块级别使用
unsafe
关键字
例如:
unsafe { int* p = &x; }
unsafe static void Copy(int* src, int* dst, int len)
直接解引用、指针算术、类型转换(如
byte* → char*
)都只能在 unsafe 块内进行

System.Runtime.CompilerServices.Unsafe:高性能的无检查内存操作

这个静态类不是语法糖,而是提供绕过 JIT 某些边界检查的底层原语,常用于高性能库(如 Span、Memory 的实现)。它不涉及

unsafe
关键字本身,但调用它的方法通常需要在 unsafe 上下文中使用其返回的指针。

常用方法:
Unsafe.As<tfrom tto>(ref TFrom source)</tfrom>
(零开销类型重解释)
Unsafe.Add<t>(T* pointer, int offset)</t>
(比
p + offset
更通用,支持泛型指针)
Unsafe.Read<t>(void* address)</t>
Unsafe.Write<t>(void* address, T value)</t>
(对齐无关的读写)
⚠️ 注意:它不保证线程安全,也不做空指针或越界检查——出错即崩溃或未定义行为

fixed 语句:固定托管对象地址,防止 GC 移动

托管堆上的对象可能被垃圾回收器移动,因此要获取其地址并用指针访问,必须用

fixed
将其“钉住”(pin)。

只适用于数组、
string
、固定大小缓冲区(
fixed int buffer[128];
)等可固定的类型
示例:
fixed (byte* ptr = bytes) { /* 使用 ptr */ }
—— 离开作用域自动解钉
不可对普通引用类型变量(如
var obj = new MyClass(); fixed (MyClass* p = &obj)
)使用
fixed
,会编译错误

stackalloc:在栈上分配原始内存块

用于快速分配小块未初始化内存,生命周期绑定到当前方法栈帧,无需 GC 管理,也无需手动释放(但不能返回给调用方)。

语法:
int* arr = stackalloc int[1024];
仅限 unsafe 方法内使用,且长度必须是编译期常量或
const
表达式(C# 7.2+ 支持局部常量)
适合临时缓冲区(如解析二进制数据)、避免堆分配开销的场景 过度使用可能导致栈溢出,需谨慎评估大小

基本上就这些。指针操作不是日常开发必需,但在高性能计算、互操作(P/Invoke)、底层集合实现或序列化库中很关键。安全第一:优先用

Span<t></t>
Memory<t></t>
ReadOnlySpan<t></t>
替代裸指针;非用不可时,务必理解生命周期、内存所有权和线程约束。

相关推荐