2012-07-16 9 views
5

कोड नीचे दिखाई दिया है प्रपत्र नेट फ्रेमवर्क:मार्शल.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

+5

मुझे लगता है कि यह मुझे स्मृति संरेखण के साथ करना है। –

+0

यह memcpy() है, हाथ से अनियंत्रित। एआरएम कोर पर आवश्यक, मुझे लगता है। –

उत्तर

6

यह अपेक्षाकृत सरल लगता है, हालांकि अनुकूलित।

बाहरी पर ध्यान दें - यह जांचने के लिए जांचता है कि क्या आप एक ऑपरेशन में Int64 लिख सकते हैं (ऐसा होता है यदि आपके द्वारा विधि को हस्ताक्षर करने वाले पॉइंटर को उचित रूप से गठबंधन किया जाता है - स्मृति में इंट 64 की शुरुआत के लिए अंक - पते की आवश्यकता होती है 8 का एक बहु हो)।

आप एक ऑपरेशन में नहीं लिख सकते हैं, कोड सिर्फ एक बाइट एक समय में लिखते हैं, कुछ समय (इस 'कहा जाता है पाश unrolling')

+0

मान लीजिए कि वे इसे 4 बाइट सीमाओं के लिए भी अनुकूलित कर सकते थे। – leppie

+0

शायद, हालांकि चेक औसत औसत पर वास्तविक अंतर बनाने के लिए बहुत महंगा हो सकता है। – zmbq

+0

'var डेटा = नया बाइट [128]; लंबी संख्या = 0x1234567890ABCDEF; निश्चित (बाइट * पी = डेटा) { * (लंबा *) (पी + 1) = संख्या; * (लंबा *) (पी +10) = संख्या; } 'पॉइंटर गठबंधन के बिना, यह कोड अच्छी तरह से काम करता है। – ldp

संबंधित मुद्दे