假设我们有一个结构数组 Entry [2] ,其在内存中的布局如下所示: [hashcode(4byte),next(4byte),hashcode(4byte),next (4byte)]
[StructLayout(LayoutKind.Explicit, Size = 8, Pack = 1)]
struct Entry
{
[FieldOffset(0)]
public int hashCode;
[FieldOffset(4)]
public int next;
}
所以现在我要在我的代码中访问此条目[0] .next
class Test
{
Entry[] entries = new Entry[2];
void AccessElement()
{
int n = entries[0].next;
}
}
因此在AccessElement方法中,我只有一行代码,即: entries [0] .next ,并且我想知道CLR如何帮助我们访问此元素。 br />
我现在有两个想法,我要给你伪代码。
1).idea 1
int n = (&entries+0)->next
获取入口对象的地址,获取第一个元素(偏移量0),然后访问成员的值(相对于该元素的基地址4字节)。
2).idea 2
Entry entry = Copy(&entries[0],8);
int n = entry.next;
将entrys对象的第一个元素(偏移量0)复制到当前堆栈中,并返回当前堆栈对象的 next 成员 entry
这两个想法是我对CLR访问结构数组中的元素成员的想法,这与我是否在某些情况下使用struct有关,毕竟大量数据移动会产生一些开销,因此有人告诉我CLR如何访问结构数组中元素成员的真实模式吗?调试和发布之间是否有区别?
谢谢
这是一个接收器代码。有人可以帮我读一下吗
Entry[] entries = new Entry[2];
00007FFB4B6D47F0 mov rcx,7FFB4B96361Ah
00007FFB4B6D47FA mov edx,2
00007FFB4B6D47FF call 00007FFBAA902630
00007FFB4B6D4804 mov qword ptr[rbp + 20h], rax
00007FFB4B6D4808 mov rax,qword ptr[rbp + 20h]
00007FFB4B6D480C mov qword ptr[rbp + 30h], rax
int n = entries[1].next;
00007FFB4B6D4810 mov rax,qword ptr[rbp + 30h]
00007FFB4B6D4814 mov edx,1
00007FFB4B6D4819 cmp rdx,qword ptr[rax + 8]
00007FFB4B6D481D jb 00007FFB4B6D4824
00007FFB4B6D481F call 00007FFBAADA2660
00007FFB4B6D4824 lea rax,[rax+rdx*8+10h]
00007FFB4B6D4829 mov eax,dword ptr[rax + 4]
00007FFB4B6D482C mov dword ptr[rbp + 2Ch], eax
也许我想得太多了?我只是看了一下IL代码:
当Entry的引用类型为
// Entry1[] entries = new Entry1[2];
IL_0001 ldc.i4.2
IL_0002 newarr ConsoleApp9.Entry1
IL_0007 stloc.0
// int n = entries[1].next;
IL_0008 ldloc.0
IL_0009 ldc.i4.1
IL_000A ldelem.ref
IL_000B ldfld System.Int32 ConsoleApp9.Entry1::next
IL_0010 stloc.1
如果Entry为类型结构,则为IL
// Entry[] entries = new Entry[2];
IL_0001 ldc.i4.2
IL_0002 newarr ConsoleApp9.Entry
IL_0007 stloc.0
// int n = entries[1].next;
IL_0008 ldloc.0
IL_0009 ldc.i4.1
IL_000A ldelema ConsoleApp9.Entry
IL_000F ldfld System.Int32 ConsoleApp9.Entry::next
IL_0014 stloc.1
对于结构化数组,指令为ldelema:将类型为(托管指针)的指定数组索引处的数组元素的地址加载到评估堆栈的顶部。
对于引用数组,指令为ldelem.ref:将包含指定数组索引处的对象引用的元素作为类型O(对象引用)加载到评估堆栈的顶部。
真相就出来了吗?