在C#中,有没有办法
编辑:
int i;
int* pi = &i;
答案 0 :(得分:14)
对于#2,&
运算符将以与C中相同的方式工作。如果变量不在堆栈中,则可能需要使用fixed
语句将其固定为你工作,所以垃圾收集器不会移动它。
对于#1,引用类型比较棘手:您需要使用GCHandle
,并且引用类型必须是blittable,即具有已定义的内存布局并且可按位进行复制。
为了以数字形式访问地址,您可以从指针类型转换为IntPtr
(定义为与指针大小相同的整数类型),并从那里转换为uint
或ulong
(取决于底层机器的指针大小)。
using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
class Blittable
{
int x;
}
class Program
{
public static unsafe void Main()
{
int i;
object o = new Blittable();
int* ptr = &i;
IntPtr addr = (IntPtr)ptr;
Console.WriteLine(addr.ToString("x"));
GCHandle h = GCHandle.Alloc(o, GCHandleType.Pinned);
addr = h.AddrOfPinnedObject();
Console.WriteLine(addr.ToString("x"));
h.Free();
}
}
答案 1 :(得分:5)
数字1根本不可能,您不能拥有指向托管对象的指针。但是,您可以使用IntPtr结构来获取有关引用中指针地址的信息:
GCHandle handle = GCHandle.Alloc(str, GCHandleType.Pinned);
IntPtr pointer = GCHandle.ToIntPtr(handle);
string pointerDisplay = pointer.ToString();
handle.Free();
对于2号,你使用&操作者:
int* p = &myIntVariable;
指针当然必须在不安全的块中完成,您必须在项目设置中允许不安全的代码。如果变量是方法中的局部变量,则它在堆栈上分配,因此它已经修复,但如果变量是对象的成员,则必须使用fixed
关键字将该对象固定在内存中,以便它没有被垃圾收集器移动。
答案 2 :(得分:3)
最正确地回答你的问题:
#1是可能的,但有点棘手,应该只是出于调试原因:
object o = new object();
TypedReference tr = __makeref(o);
IntPtr ptr = **(IntPtr**)(&tr);
这适用于任何对象,并实际返回内存中对象的内部指针。请记住,地址可以随时更改,因为GC喜欢在内存中移动对象。
#2指针不是对象,因此不会从它们继承 ToString 。您必须像以下那样将指针强制转换为 IntPtr :
Console.WriteLine((IntPtr)pi);