SoFunction
Updated on 2025-03-07

Detailed explanation of C# fixed size buffer and using pointers to copy data

Fixed-size buffers

AvailablefixedKeyword creates a buffer with a fixed-size array in the data structure (buffer). Fixed-size buffers are useful when writing methods that interoperate with data sources in other languages ​​or platforms.

You can use regular structure members (regular struct members) can be used on any attribute or modifierfixed-size buffer

The only limitation is that the array type must be the base type bool, byte, char, short, int, long, sbyte, ushort, uint, ulong, float, or double.

for example:

private fixed char name[30];

In security code, a C# structure containing an array does not contain any array elements, the structure is just a reference to the element.

existunsafeIn the code block, it can bestructAdd a fixed-size array.

underPathArray structThe size does not depend on the number of array elements, becausepathNameQuote variables:

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

In the unsafe code,structA structure can contain embedded arrays. In the following example,fixedBufferThe array has a fixed size, usingfixedThe statement takes the pointer to the first element and accesses the array element through that pointer.fixedStatement pin instance fieldfixedBufferto a specific location in memory.

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 = )
        {
            *charPtr = 'A';
        }
        // Access safely through the index:
        char c = [0];
        (c);
        // Modify through the index:
        [0] = 'B';
        ([0]);
    }
}

128 elementscharThe array size is 256 bytes. Fixed sizecharEach character in the buffer is fixedly occupied two bytes, regardless of the encoding used.

The size of the array is the same, even if the char buffer is marshaled to the API method or structurestructSet asCharSet = / CharSet =

Fixed sizeboolAn array whose elements occupy a fixed size of 1 byte.boolArrays are not suitable for creating bit arrays or buffers.

CharSet

Fixed-size buffer useCompile to indicate that a common language runtime (CLR) type contains an unmanaged array that may overflow.

usestackallocThe allocated memory also automatically enables buffer overflow detection in the CLR.

unsafe structFixed-size buffers can be used in it. For example, the previous oneBuffer

internal unsafe struct Buffer
{
    public fixed char fixedBuffer[128];
}

The compiler will generate the following featuresBuffer

internal struct Buffer
{
    [StructLayout(, Size = 256)]
    [CompilerGenerated]
    [UnsafeValueType]
    public struct <fixedBuffer>e__FixedBuffer
    {
        public char FixedElementField;
    }
    [FixedBuffer(typeof(char), 128)]
    public <fixedBuffer>e__FixedBuffer fixedBuffer;
}

Several ways in which a fixed-size buffer is different from a regular array are as follows:

  • Only inunsafeUsed in context
  • Only as an instance field of a structure
  • Always a vector or a one-dimensional array.
  • The declaration shall include length, such asfixed char id[8], cannot be usedfixed char id[]

How to copy an array of bytes using pointers

The following passunsafeKeywords enable pointers to be used in Copy methods;fixedStatements are used to declaresourceanddestinationPointer to the array.

fixedThe position of the statement pin source and target array in memory is not moved by garbage collection. whenfixedAfter block execution is completed, the memory block of the array will be unfixed (unpinned)。

This example uses index(indices-Metrics) instead of a second unmanaged pointer to access elements of two arrays.pSourceandpTargetPointer declaration fixed array.

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 ("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 ("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 (( - sourceOffset < count) ||
        ( - targetOffset < count))
    {
        throw new ("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];
        }
    }
}

refer to

  • Unsafe code, pointer types, and function pointers

The above is the detailed explanation of C# fixed-size buffer and the use of pointers to copy data. For more information about C# fixed-size buffer, please pay attention to my other related articles!