C#内存地址和变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/588817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# memory address and variable
提问by Ray Lu
in C#, is there a way to
在 C# 中,有没有办法
- Get the memory address stored in a reference type variable?
- Get the memory address of a variable?
- 获取存储在引用类型变量中的内存地址?
- 获取变量的内存地址?
EDIT:
编辑:
int i;
int* pi = &i;
- How do you print out the hex value of pi?
- 你如何打印出pi的十六进制值?
采纳答案by Jeffrey Hantin
For #2, the &
operator will work in the same fashion as in C. If the variable is not on the stack, you may need to use a fixed
statement to pin it down while you work so the garbage collector does not move it, though.
对于#2,&
操作符将以与 C 中相同的方式工作。如果变量不在堆栈中,您可能需要在工作时使用fixed
语句将其固定,这样垃圾收集器就不会移动它。
For #1, reference types are trickier: you'll need to use a GCHandle
, and the reference type has to be blittable, i.e. have a defined memory layout and be bitwise copyable.
对于#1,引用类型更棘手:您需要使用 a GCHandle
,并且引用类型必须是 blittable,即具有定义的内存布局并且可以按位复制。
In order to access the address as a number, you can cast from pointer type to IntPtr
(an integer type defined to be the same size as a pointer), and from there to uint
or ulong
(depending on the pointer size of the underlying machine).
为了以数字形式访问地址,您可以从指针类型转换为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();
}
}
回答by Guffa
Number 1 is not possible at all, you can't have a pointer to a managed object. However, you can use an IntPtr structure to get information about the address of the pointer in the reference:
数字 1 根本不可能,您不能拥有指向托管对象的指针。但是,您可以使用 IntPtr 结构来获取有关引用中指针地址的信息:
GCHandle handle = GCHandle.Alloc(str, GCHandleType.Pinned);
IntPtr pointer = GCHandle.ToIntPtr(handle);
string pointerDisplay = pointer.ToString();
handle.Free();
For number 2 you use the & operator:
对于数字 2,您使用 & 运算符:
int* p = &myIntVariable;
Pointers of course have to be done in a unsafe block, and you have to allow unsafe code in the project settings. If the variable is a local variable in a method, it's allocated on the stack so it's already fixed, but if the variable is a member of an object, you have to pin that object in memory using the fixed
keyword so that it's not moved by the garbage collector.
指针当然必须在不安全的块中完成,并且您必须在项目设置中允许不安全的代码。如果变量是方法中的局部变量,它会在堆栈上分配,因此它已经固定,但是如果变量是对象的成员,则必须使用fixed
关键字将该对象固定在内存中,以便它不会被垃圾收集器。
回答by IllidanS4 wants Monica back
To answer your question most correctly:
要最正确地回答您的问题:
#1 is possible but a bit tricky, and should be only done for debugging reasons:
#1 是可能的,但有点棘手,并且应该仅出于调试原因而进行:
object o = new object();
TypedReference tr = __makeref(o);
IntPtr ptr = **(IntPtr**)(&tr);
This works for any object and actually returns the internal pointer to the object in memory. Remember the address can change at any moment because of the GC, which likes to move objects across the memory.
这适用于任何对象,实际上返回指向内存中对象的内部指针。请记住,由于 GC 喜欢在内存中移动对象,因此地址可能随时更改。
#2 Pointers aren't objects and thus don't inherit ToStringfrom them. You have to cast the pointer to IntPtrlike so:
#2 指针不是对象,因此不会从它们继承ToString。您必须像这样将指针转换为IntPtr:
Console.WriteLine((IntPtr)pi);