日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C#固定大小緩沖區及使用指針復制數據詳解_C#教程

作者:codemissing ? 更新時間: 2023-01-10 編程語言

固定大小的緩沖區 - Fixed-size buffers

可以使用 fixed 關鍵字創建在數據結構中具有固定大小的數組的緩沖區(buffer)。當編寫與其他語言或平臺的數據源進行互操作的方法時,固定大小的緩沖區很有用。

在可以使用常規結構成員(regular struct members)的任何屬性或修飾符上都可以使用fixed-size buffer

唯一的限制是數組類型必須為基礎類型 bool、byte、char、short、int, long、sbyte、ushort、uint、ulong、float 或 double。

比如:

private fixed char name[30];

在安全代碼中,包含數組的C#結構不會包含任何數組元素,結構只是包含到元素的引用。

unsafe代碼塊中,可以為struct添加固定大小的數組。

下面 PathArray struct 的大小不取決于數組元素的數量,因為是pathName引用變量:

public struct PathArray
{
    public char[] pathName;
    private int reserved;
}

不安全代碼中,struct結構可以包含嵌入的數組。下面的示例中,fixedBuffer數組有一個固定大小,使用fixed語句獲取第一個元素的指針,并通過該指針訪問數組元素。fixed語句pin實例字段fixedBuffer到內存中的一個特定位置。

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數組大小是256個字節。固定大小的char緩沖區中每個字符固定占兩個字節,不管采用哪種編碼。

數組的大小是相同的,即使char緩沖區被封送到 API 方法或結構struct設置為CharSet = CharSet.Auto / CharSet = CharSet.Ansi

固定大小的bool數組,其元素占用的大小固定為1字節。bool數組不適合創建位數組或緩沖區。

CharSet

固定大小的緩沖區使用 System.Runtime.CompilerServices.UnsafeValueTypeAttribute 進行編譯,指示公共語言運行時 (CLR) 某個類型包含可能溢出的非托管數組。

使用 stackalloc 分配的內存還會在 CLR 中自動啟用緩沖區溢出檢測功能。

unsafe struct 中可以使用固定大小的緩沖區。比如前面的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;
}

固定大小的緩沖區不同于常規數組的幾個方式如下:

  • 只能在unsafe上下文中使用
  • 只能作為結構的實例字段
  • 始終是矢量或一維數組。
  • 聲明應包括長度,如 fixed char id[8],不能使用 fixed char id[]

如何使用指針復制字節數組

下面的通過unsafe關鍵字使Copy方法中可以使用指針;fixed語句用于聲明sourcedestination數組的指針。

fixed語句pin源和目標數組在內存中的位置不被垃圾收集移動。當fixed塊執行結束后,數組的內存塊會解除固定(unpinned)。

該示例使用索引(indices-指標)而不是第二個非托管指針訪問兩個數組的元素。pSourcepTarget 指針的聲明固定數組。

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];
        }
    }
}

參考

  • Unsafe code, pointer types, and function pointers

原文鏈接:https://juejin.cn/post/7175167895406641189

欄目分類
最近更新