C#默认禁止unsafe代码,需显式启用;指针声明为T*,托管对象须用fixed固定或分配非托管内存;fixed仅在块内有效,指针不可逃逸;指针性能优势限于特定场景。
为什么C#里写unsafe代码会编译失败
默认情况下,C#编译器禁止不安全上下文,直接写指针会报错 CS0227: Unsafe code may only appear if compiling with /unsafe。必须显式开启支持,否则连最基础的int* p都会被拦住。
解决方法只有两个:
• 项目文件(.csproj)里加 true
• 或命令行编译时加参数 /unsafe
• Visual Studio 用户:右键项目 →「属性」→「生成」→ 勾选「允许不安全代码」
在unsafe块里怎么声明和初始化指针
指针类型语法是 T*,比如 int*、byte*,不能直接指向托管对象(如普通数组或类实例),除非先“固定”它。常见错误是试图这样写:int[] arr = new int[10]; int* p = arr;——这会编译失败,因为数组在GC堆上,地址可能随时变动。
正确做法分三步:
• 用 fixed 语句固定托管内存:fixed (int* p = arr) { /* 使用 p */ }
• 或分配非托管内存:int* p = (int*)Marshal.AllocHGlobal(10 * sizeof(int));(记得后续 Marshal.FreeHGlobal((IntPtr)p))
• 局部栈内存可用 stackalloc:int* p = stackalloc int[10];(无需手动释放,但仅限方法内有效)
fixed语句的生命周期和常见陷阱
fixed只在语句块内有效,离开作用域自动“解固定”。很多人误以为固定后可以保存指针到字段或返回给调用方,这是危险的——比如:private int* _ptr; void Foo() { fixed (int* p = arr) { _ptr = p; } },此时_ptr已指向可能被移动或回收的内存,后续读写大概率触发访问冲突或静默数据损坏。