C#固定大小緩沖區(qū)及使用指針復(fù)制數(shù)據(jù)詳解
固定大小的緩沖區(qū) - Fixed-size buffers
可以使用 fixed 關(guān)鍵字創(chuàng)建在數(shù)據(jù)結(jié)構(gòu)中具有固定大小的數(shù)組的緩沖區(qū)(buffer)。當(dāng)編寫與其他語言或平臺的數(shù)據(jù)源進行互操作的方法時,固定大小的緩沖區(qū)很有用。
在可以使用常規(guī)結(jié)構(gòu)成員(regular struct members)的任何屬性或修飾符上都可以使用fixed-size buffer。
唯一的限制是數(shù)組類型必須為基礎(chǔ)類型 bool、byte、char、short、int, long、sbyte、ushort、uint、ulong、float 或 double。
比如:
private fixed char name[30];
在安全代碼中,包含數(shù)組的C#結(jié)構(gòu)不會包含任何數(shù)組元素,結(jié)構(gòu)只是包含到元素的引用。
在unsafe代碼塊中,可以為struct添加固定大小的數(shù)組。
下面 PathArray struct 的大小不取決于數(shù)組元素的數(shù)量,因為是pathName引用變量:
public struct PathArray
{
public char[] pathName;
private int reserved;
}
不安全代碼中,struct結(jié)構(gòu)可以包含嵌入的數(shù)組。下面的示例中,fixedBuffer數(shù)組有一個固定大小,使用fixed語句獲取第一個元素的指針,并通過該指針訪問數(shù)組元素。fixed語句pin實例字段fixedBuffer到內(nèi)存中的一個特定位置。
internal unsafe struct Buffer
{
public fixed char fixedBuffer[128];
}
internal unsafe class Example
{
public Buffer buffer = default;
}
private static void AccessEmbeddedArray()
{
var example = new Example();
unsafe
{
// Pin the buffer to a fixed location in memory.
fixed (char* charPtr = example.buffer.fixedBuffer)
{
*charPtr = 'A';
}
// Access safely through the index:
char c = example.buffer.fixedBuffer[0];
Console.WriteLine(c);
// Modify through the index:
example.buffer.fixedBuffer[0] = 'B';
Console.WriteLine(example.buffer.fixedBuffer[0]);
}
}
128個元素的char數(shù)組大小是256個字節(jié)。固定大小的char緩沖區(qū)中每個字符固定占兩個字節(jié),不管采用哪種編碼。
數(shù)組的大小是相同的,即使char緩沖區(qū)被封送到 API 方法或結(jié)構(gòu)struct設(shè)置為CharSet = CharSet.Auto / CharSet = CharSet.Ansi
固定大小的bool數(shù)組,其元素占用的大小固定為1字節(jié)。bool數(shù)組不適合創(chuàng)建位數(shù)組或緩沖區(qū)。
固定大小的緩沖區(qū)使用 System.Runtime.CompilerServices.UnsafeValueTypeAttribute 進行編譯,指示公共語言運行時 (CLR) 某個類型包含可能溢出的非托管數(shù)組。
使用 stackalloc 分配的內(nèi)存還會在 CLR 中自動啟用緩沖區(qū)溢出檢測功能。
unsafe struct 中可以使用固定大小的緩沖區(qū)。比如前面的Buffer:
internal unsafe struct Buffer
{
public fixed char fixedBuffer[128];
}
編譯器會生成下面帶特性的Buffer:
internal struct Buffer
{
[StructLayout(LayoutKind.Sequential, Size = 256)]
[CompilerGenerated]
[UnsafeValueType]
public struct <fixedBuffer>e__FixedBuffer
{
public char FixedElementField;
}
[FixedBuffer(typeof(char), 128)]
public <fixedBuffer>e__FixedBuffer fixedBuffer;
}
固定大小的緩沖區(qū)不同于常規(guī)數(shù)組的幾個方式如下:
- 只能在
unsafe上下文中使用 - 只能作為結(jié)構(gòu)的實例字段
- 始終是矢量或一維數(shù)組。
- 聲明應(yīng)包括長度,如
fixed char id[8],不能使用fixed char id[]。
如何使用指針復(fù)制字節(jié)數(shù)組
下面的通過unsafe關(guān)鍵字使Copy方法中可以使用指針;fixed語句用于聲明source和destination數(shù)組的指針。
fixed語句pin源和目標(biāo)數(shù)組在內(nèi)存中的位置不被垃圾收集移動。當(dāng)fixed塊執(zhí)行結(jié)束后,數(shù)組的內(nèi)存塊會解除固定(unpinned)。
該示例使用索引(indices-指標(biāo))而不是第二個非托管指針訪問兩個數(shù)組的元素。pSource 和 pTarget 指針的聲明固定數(shù)組。
static unsafe void Copy(byte[] source, int sourceOffset, byte[] target,
int targetOffset, int count)
{
// If either array is not instantiated, you cannot complete the copy.
if ((source == null) || (target == null))
{
throw new System.ArgumentException("source or target is null");
}
// If either offset, or the number of bytes to copy, is negative, you
// cannot complete the copy.
if ((sourceOffset < 0) || (targetOffset < 0) || (count < 0))
{
throw new System.ArgumentException("offset or bytes to copy is negative");
}
// If the number of bytes from the offset to the end of the array is
// less than the number of bytes you want to copy, you cannot complete
// the copy.
if ((source.Length - sourceOffset < count) ||
(target.Length - targetOffset < count))
{
throw new System.ArgumentException("offset to end of array is less than bytes to be copied");
}
// The following fixed statement pins the location of the source and
// target objects in memory so that they will not be moved by garbage
// collection.
fixed (byte* pSource = source, pTarget = target)
{
// Copy the specified number of bytes from source to target.
for (int i = 0; i < count; i++)
{
pTarget[targetOffset + i] = pSource[sourceOffset + i];
}
}
}
參考
以上就是C#固定大小緩沖區(qū)及使用指針復(fù)制數(shù)據(jù)詳解的詳細(xì)內(nèi)容,更多關(guān)于C# 固定大小緩沖區(qū)的資料請關(guān)注腳本之家其它相關(guān)文章!
- C#環(huán)形緩沖區(qū)(隊列)完全實現(xiàn)
- C#讀取中文字符及清空緩沖區(qū)的實現(xiàn)代碼
- 關(guān)于C#?調(diào)用Dll?傳遞字符串指針參數(shù)的問題
- C#調(diào)用帶結(jié)構(gòu)體指針Dll的方法
- 深入理解C#指針之美
- 關(guān)于C#調(diào)用C++dll傳指針釋放內(nèi)存問題
- C#實現(xiàn)復(fù)制數(shù)據(jù)庫 C#將A數(shù)據(jù)庫數(shù)據(jù)轉(zhuǎn)到B數(shù)據(jù)庫
- C#使用SqlBulkCopy批量復(fù)制數(shù)據(jù)到數(shù)據(jù)表
相關(guān)文章
WPF自定義TreeView控件樣式實現(xiàn)QQ聯(lián)系人列表效果
TreeView控件在項目中使用比較頻繁,下面這篇文章主要給大家介紹了關(guān)于WPF自定義TreeView控件樣式實現(xiàn)QQ聯(lián)系人列表效果的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。2018-04-04
C#如何使用Bogus創(chuàng)建模擬數(shù)據(jù)示例代碼

