2012-07-16 51 views
5

下面的代码是被反映的形式.Net框架:为什么Marshal.WriteInt64方法的代码如此复杂?

[SecurityCritical] 
public static unsafe void WriteInt64(IntPtr ptr, int ofs, long val){ 
    try{ 
     byte* numPtr = (byte*) (((void*) ptr) + ofs); 
     if ((((int) numPtr) & 7) == 0){ 
      *((long*) numPtr) = val; 
     } 
     else{ 
      byte* numPtr2 = (byte*) &val; 
      numPtr[0] = numPtr2[0]; 
      numPtr[1] = numPtr2[1]; 
      numPtr[2] = numPtr2[2]; 
      numPtr[3] = numPtr2[3]; 
      numPtr[4] = numPtr2[4]; 
      numPtr[6] = numPtr2[6]; 
      numPtr[7] = numPtr2[7]; 
     } 
    } 
    catch (NullReferenceException){ 
     throw new AccessViolationException(); 
    } 
} 

在我看来,*((long*) numPtr) = val是不够的,非常有效的。

为什么这么复杂?

+0

也许是与endiens? 。 – KingCronus 2012-07-16 08:57:49

+5

看起来更像是与我的内存对齐。 – 2012-07-16 09:00:56

+0

这是memcpy(),手工展开。我想,在ARM内核上是必需的。 – 2012-07-16 10:04:56

回答

6

虽然优化,但看起来相当简单。

请注意外部if - 它检查是否可以在一个操作中编写Int64(如果您将该方法的指针调整为properlty,则会发生这种情况 - 指向内存中Int64的起始位置 - 地址需要是8的倍数)。

如果你不能在一个操作中写代码只是在一次写一个字节,跳过循环来节省一些时间(这被称为“循环展开”)

+0

猜猜他们可以优化它的4字节边界。 – leppie 2012-07-16 09:06:42

+0

也许,虽然支票本身可能过于昂贵,平均来说实际上并没有什么区别。 – zmbq 2012-07-16 09:07:29

+0

'var data = new byte [128]; long num = 0x1234567890ABCDEF;固定(字节* p =数据) * *(long *)(p + 1)= num; *(long *)(p + 10)= num; '没有指针对齐,这段代码运行良好。 – ldp 2012-07-16 09:10:20

相关问题