如何在C#中访问结构数组中元素的成员

时间:2019-05-08 04:08:39

标签: c#

假设我们有一个结构数组 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的引用类型为

时,这是IL
        // 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(对象引用)加载到评估堆栈的顶部。

真相就出来了吗?

0 个答案:

没有答案
相关问题