2011-07-24 37 views
2


我想知道 - 对象是如何存储在内存中的?
我已经知道有一个引用(就像一个指针),它是一个int值,它包含存储该对象的内存中的位置 - 但它存储的究竟是什么?
可以说我有ClassCint a, char b, long c, float dshort e - 我知道每个如何存储每一个都有自己的一套位,但在每一个不同的位的数量 - 所以究竟怎样C#知道哪些位应该访问它,当我写OBJ.cOBJ.b
是否有可能将整个(非静态)对象转换为字节数组bit \位置和返回?

明显 - 如果有像ClassC.TcpListener tcp这样的东西 - 它是一个引用并存储为int(至少它具有相同的字节大小) - 但是,它仍然如何在int和指针之间有所不同?
C#中的对象如何存储在内存中?

+1

”但它究竟存储了多少?“ - 你能澄清一下你在找什么吗?堆vs堆栈? Endieness?还有别的吗? – Oded

+1

请注意,这里的大多数答案将是一个实现细节。引用很大程度上是不透明的 - 即使它在大多数情况下碰巧是一个指针,它也不是必需的。也;在x64引用是64位,而不是32(“int”) –

+1

此外,ECMA-335会给你一个完整的答案。当然,它有点干燥。 –

回答

1

通常,这不是你需要关心的东西,除非你是P /调用C库。

那么C#如何知道当我写入 OBJ.c或OBJ.b时应该访问哪些位?

这取决于对象的StructLayout。有两种可能的LayoutKind s。

缺省值为Sequential,其中字段以与声明相同的顺序存储,aligned正确。默认情况下,包含你的五场一个struct将被存储为:

  • 偏移0-3:int a
  • 偏移4-5:char b
  • 偏移6-7:填充
  • 偏移8 15:long c
  • 偏移16-19:float d
  • 偏移20-21:short e

由于vtable指针,垃圾回收器元数据等原因,A class可能会有略微不同的布局。我不确定它是如何工作的。

其他LayoutKind是显式的,您可以在其中明确指定字段偏移量。

是否有可能将整个(非静态)对象转换为一个字节数组\位和回?

是的,Marshal类会让你这样做。请参阅StructureToPtrPtrToStructure

它是一个参考,并存储为int

指针不是存储为int秒。这在64位系统上不起作用。代替使用IntPtr

但仍然,int和指针之间有什么区别?

在哪个级别? C#? CIL?机器语言? “

+0

“对象的StructLayout”似乎有些矛盾...... –

+0

我会检查它。谢谢! –

+0

'Marshal'类不会让你看看它们在内存中的字节,至少并不总是如此。它所做的是将其转换为适合非托管代码的表单。翻译通常不会做任何事情,但并非总是如此。 – svick

2

C#实际上不知道在哪里访问对象中的成员。它是决定对象布局的JIT编译器。

可以为成员添加属性,以便JIT编译器以特定的方式放置成员,这样可以将所有成员作为内存块访问,但这很少值得付出。

注意:指针在32位系统上是32位(int),在64位系统上是64位(长)。

+0

所以这就是为什么64位系统需要一堆内存>< –