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