C#固定大小缓冲区及使用指针复制数据详解

作者:codemissing

这篇文章主要为大家介绍了C#固定大小缓冲区及使用指针复制数据详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

固定大小的缓冲区 - 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];

以上就是C#固定大小缓冲区及使用指针复制数据详解的详细内容,更多关于C# 固定大小缓冲区的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
  • C# wpf 无边框窗口添加阴影效果的实现
    C# wpf 无边框窗口添加阴影效果的实现
    2022-11-11
  • C#实现Oracle批量写入数据的方法详解
    C#实现Oracle批量写入数据的方法详解
    2022-11-11
  • C#实现UI控件输出日志的方法详解
    C#实现UI控件输出日志的方法详解
    2022-10-10
  • C# WinForm自动更新程序之文件上传操作详解
    C# WinForm自动更新程序之文件上传操作详解
    2022-10-10
  • C#固定大小缓冲区及使用指针复制数据详解
    C#固定大小缓冲区及使用指针复制数据详解
    2022-10-10
  • C#使用stackalloc分配堆栈内存和非托管类型详解
    C#使用stackalloc分配堆栈内存和非托管类型详解
    2022-10-10
  • 使用C# 11的静态接口方法改进 面向约定 的设计方法
    使用C# 11的静态接口方法改进 面向约定 的设计方法
    2022-10-10
  • C# Winform文本面板带滚动条的实现过程
    C# Winform文本面板带滚动条的实现过程
    2022-10-10
  • 美国设下计谋,用娘炮文化重塑日本,已影响至中国
    美国设下计谋,用娘炮文化重塑日本,已影响至中国
    2021-11-19
  • 时空伴随者是什么意思?时空伴随者介绍
    时空伴随者是什么意思?时空伴随者介绍
    2021-11-09
  • 工信部称网盘企业免费用户最低速率应满足基本下载需求,天翼云盘回应:坚决支持,始终
    工信部称网盘企业免费用户最低速率应满足基本下载需求,天翼云盘回应:坚决支持,始终
    2021-11-05
  • 2022年放假安排出炉:五一连休5天 2022年所有节日一览表
    2022年放假安排出炉:五一连休5天 2022年所有节日一览表
    2021-10-26
  • 电脑版 - 返回首页

    2006-2023 脚本之家 JB51.Net , All Rights Reserved.
    苏ICP备14036222号