久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

C# 內(nèi)存操作常用函數(shù)

 戴維圖書館 2019-05-11

寫這篇文章是有一個(gè)起因的...

最近在學(xué)socket編程 翻源代碼的時(shí)候 無(wú)意發(fā)現(xiàn)一個(gè)沒有用過(guò)的函數(shù)Marshal.UnsafeAddrOfPinnedArrayElement()
它的原形如下:

public static IntPtr UnsafeAddrOfPinnedArrayElement(Array arr, int index);

這個(gè)靜態(tài)函數(shù)的作用是返回一個(gè)數(shù)組第index個(gè)元素的首地址
而且沒有值類型和引用類型的限制 沒有數(shù)組索引越界的檢查
簡(jiǎn)單的說(shuō) 它是一個(gè)托管的C#數(shù)組與非托管指針的一個(gè)合法的轉(zhuǎn)換接口

這樣 我們就很容易寫出以下代碼了:

  1. unsafe
  2. {
  3. byte[] array = new byte[1024];
  4. byte* pArray = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(array, 0);
  5. for (int i = 0, j = array.Length; i < j; i++)
  6. {
  7. (pArray[i])++;
  8. }
  9. }

他的好處是 在改變數(shù)組值的時(shí)候沒有進(jìn)行索引越界檢查 效率會(huì)略微提高

當(dāng)然 它只在極端需要效率的場(chǎng)合值得一用 或者是密集計(jì)算的場(chǎng)合懶得用C++寫底層然后dllImport的時(shí)候用
它比普通的數(shù)組遍歷能提高5%~15%的效能
畢竟 指針玩不好終究是個(gè)挺危險(xiǎn)的東西..

另外一個(gè)有趣的函數(shù)是Buffer.BlockCopy()
原形如下:

public static void BlockCopy(Array src, int srcOffset, Array dst, int dstOffset, int count);

它也是用來(lái)復(fù)制內(nèi)存區(qū)塊的 和Array.Copy()不同 它最后一個(gè)參數(shù)count是表示復(fù)制的字節(jié)長(zhǎng)度 而不是復(fù)制元素的數(shù)量
當(dāng)然 這個(gè)函數(shù)的源數(shù)組和目的數(shù)組 類型可以不同 但是必須是基本類型(原始的各種數(shù)值型)

大致用法是這樣:

  1. double[] src = new double[5] { 1, 2, 3, 4, 5 };
  2. byte[] dst = new byte[40];
  3. Buffer.BlockCopy(src, 0, dst, 0, 40);

于是它就會(huì)按照double的IEEE內(nèi)存標(biāo)準(zhǔn) 原封不動(dòng)的復(fù)制到byte[]里去了...
事實(shí)上用上面提供的數(shù)組轉(zhuǎn)指針 以及Marshal.Copy()方法也可以做到 不過(guò)這函數(shù)方便了很多

BitConverter類中提供了一系列靜態(tài)函數(shù) 如GetBytes()和ToInt32()等 可以在基本類型和byte[]間進(jìn)行轉(zhuǎn)換
它比較適合單一轉(zhuǎn)換的場(chǎng)合 如果需要循環(huán)轉(zhuǎn)換的話還是使用BlockCopy或者直接unsafe指針讀取更為方便

Marshal.Copy()提供了一系列的重載 可以提供托管數(shù)組和IntPtr之間的內(nèi)存復(fù)制功能...
于是經(jīng)常我們會(huì)看到一段GDI圖像處理代碼如下:

  1. Bitmap bitmap = (Bitmap)Bitmap.FromFile(fileName);
  2. BitmapData data = bitmap.LockBits(new Rectangle(new Point(), bitmap.Size), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
  3. byte[] buffer = new byte[data.Stride * data.Height];
  4. Marshal.Copy(data.Scan0, buffer, 0, buffer.Length);
  5. for (int h = 0; h < data.Height; h++)
  6. {
  7. for (int w = 0; w < data.Width; w++)
  8. {
  9. //...
  10. }
  11. }
  12. Marshal.Copy(buffer, 0, data.Scan0, buffer.Length);
  13. bitmap.UnlockBits(data);

事實(shí)上 直接使用指針可以在不創(chuàng)建緩沖區(qū)的情況下對(duì)非托管數(shù)據(jù)進(jìn)行操作
如果是對(duì)一定批量的非托管數(shù)據(jù)進(jìn)行處理 可以使用緩沖區(qū)(如上面的情況可以圖像逐行復(fù)制處理)
或者直接使用unsafe代碼 更為高效

另外一件比較討厭的事 Marshal.Copy()沒有提供從指針到指針復(fù)制的函數(shù)重載 不過(guò)我們可以用API來(lái)實(shí)現(xiàn)它:

  1. [DllImport("kernel32.dll")]
  2. public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);

IntPtr當(dāng)然也可以使用void*來(lái)替代或者重載 以達(dá)到更好的靈活性
結(jié)合數(shù)組取地址的方式 這個(gè)函數(shù)可以提供不同類型的 非基礎(chǔ)類型數(shù)組之間的復(fù)制

總之 因?yàn)镃#的特殊支持 可以很輕松的直接處理內(nèi)存 寫出類似C++的指針運(yùn)算代碼
在保證足夠安全性的前提下  它會(huì)帶來(lái)意想不到的語(yǔ)法便利 以及高效的處理速率

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多