带代码的C#内存地址扩展

带代码的C#内存地址扩展,c#,C#,我得到了下面的MemoryAddressExtension代码,它在C中显示了对象地址# 想知道是什么吗 IntPtr** 及 谢谢 public static class MemoryAddressExtenstion { public static string Address(this object me) { unsafe { TypedReference tr = __makeref(me);

我得到了下面的MemoryAddressExtension代码,它在C中显示了对象地址#

想知道是什么吗

IntPtr**

谢谢

public static class MemoryAddressExtenstion
{
    public static string Address(this object me)
    {
        unsafe
        {
            TypedReference tr = __makeref(me);
            var ptr = **(IntPtr**)&tr;
            return "0x" + ptr.ToString("X");
        }
    }
}


< C/> P> < P> <代码> *> /COD>常用于C/C++中指向指针。code>IntPtr**要求提供指向
IntPtr的指针的指针

**(IntPtr**)和tr对上述结构的引用


< >可以使用C语言,但是我建议你多学一些关于C++的知识,因为在这些语言中更普遍。

< P>遗憾的是我不能用更好的方式解释它们。所以,如果有人能纠正我,那么谢谢

NET中称为“引用”,C中称为“指针”。因此,在C#中所谓的
object me
就是一个
void*me
,一个指向对象的指针(称为
me

TypedReference tr = __makeref(me);
这将创建变量
me
TypedReference
。正如我所说,引用非常类似于C指针(事实上,如果你看一下is,你会发现它包含一个
IntPtr值
)。因此,在C中,它将是:

void **tr = &me;
(在.NET中是指向
类型引用的指针,在C中是指向指针的指针)

现在,代码正在创建第三级间接性

void ***temp = &tr;
然后是两次去引用它

void *ptr = **temp;
因此,我们有一个
*ptr
,它与初始的
*me
相同。我们这样做是因为通常在C#中,您不能直接将引用转换为等效指针


他们为什么要这样做?因为您通常不能将引用强制转换为指针(您不能
(IntPtr)me
),也不能直接获取引用地址(因此您不能
&me
)。但是您可以创建一个
类型隔离
,它相当于执行
&me
。现在,很遗憾,您不能执行
(IntPtr*)tr
,或
(IntPtr)tr
。但幸运的是,您可以
&tr
。现在,您终于能够获得一个真正的指针了,您可以开始解除它的限制以返回到您想要的初始指针。

从一开始,一个
IntPtr
就是一个

类型名称后面的
*
表示指向前面类型的指针。所以
IntPtr*
意味着指向
IntPtr
的指针。而
IntPtr**
表示指向
IntPtr
的指针

当类型位于表达式前面的括号中时,它是类型转换操作。因此
(IntPtr**)x
意味着将
x
转换为
IntPtr**

运算符是。因此
&tr
意味着获取值的地址
tr
。由于
tr
属于类型,因此结果值的类型指针指向
TypedReference*

表达式前面的
*
运算符是,它返回给定地址处的值。因此,
*x
是获取
x
指向的内存位置的值。而
**x
是获取指向
*x
的内存位置的值。这意味着x是指向指针的指针

但乍一看,这会产生垃圾。我们正在从
TypedReference*
转换为
IntPtr**
。它之所以有效,是因为指向原始对象的

一般来说,这是一个危险的小把戏,使用时应非常小心,因为:

  • 对象的内存地址移动(您可以使用
    GCHandle.Alloc
    fixed
    关键字锁定它们)
  • \uuuu makref
    是该语言中未记录且不受支持的部分
  • 这取决于
    TypedRef
  • 它不是可移植代码

  • <>你从哪里把代码从中理解的?我建议你在C++中查找指针,这会帮助你减少它,因为它在C/C++中比C语言更常见。
    **
    表示指向指针的指针。如果有人想知道
    \uuu makeref
    到底是什么,请看。使用github源代码更新code@MatthewWatson,谢谢,我把它放在参考资料里了too@Amit是的,我知道C#中有指针,但并不常见。这就是为什么我建议读C/C++来了解它更多的原因,因为它在那里更常见。@ Amit谢谢你让我知道,我添加了你的答案链接。一个重要的点是<代码> TypedReference < /Cult> Stutt从<代码>
包含一个名为
Value
IntPtr
字段作为其第一个字段,该字段指向感兴趣的对象,因此强制转换以该值结束。(请参阅。)如果Microsoft通过在
字段前面添加新字段来更改
类型引用
的布局,则强制转换将不再返回正确的值。@MatthewWatson Yep。我以为是那样的,但我没有看一眼。和往常一样,做无证的事情就像玩弄命运。
void *ptr = **temp;