Working with Pointers and Unsafe Code in C#

C# enables direct memory manipulation through unsafe code blocks, which are essential for enteroperating with native systems, optimizing performance-critical algorithms, or accessing hardware resources. Unlike managed code, unsafe sections bypass the .NET Common Language Runtime's memory safety guarantees, requiring explicit use of the unsafe modifier. This article explores pointer operations, memory management techniques, and safe usage patterns with in unsafe contexts.

Pointer Fundamentals

Pointers in C# require unsafe context and support address-of (&), dereference (*), and size-of (sizeof) operations. Only value types (structs, primitives) can have their addresses taken; reference types (classes, strings) are managed by the garbage collector and cannot be directly addressed.

unsafe class PointerDemo
{
    struct Coordinate
    {
        public int X;
        public int Y;
    }

    public static void Main()
    {
        Coordinate pos = new Coordinate { X = 10, Y = 20 };
        Coordinate* location = &pos;
        int* xAddr = &location->X;
        int* yAddr = &location->Y;

        Console.WriteLine($"Struct address: 0x{&pos:X}");
        Console.WriteLine($"Struct size: {sizeof(Coordinate)} bytes");
        Console.WriteLine($"X address: 0x{xAddr:X}, Y address: 0x{yAddr:X}");
    }
}

Fixed Statement for Pinning

When working with managed objects (e.g., classes), the garbage collector may relocate memory. The fixed statement prevents this by pinning objects in place during pointer operations.

unsafe class ManagedPointerDemo
{
    class DataContainer
    {
        public int Value;
        public static int StaticValue;
    }

    public static void Main()
    {
        DataContainer data = new DataContainer();
        fixed (int* valuePtr = &data.Value)
            Console.WriteLine($"Instance address: 0x{valuePtr:X}");

        fixed (int* staticPtr = &DataContainer.StaticValue)
            Console.WriteLine($"Static address: 0x{staticPtr:X}");

        int[] buffer = new int[5];
        fixed (int* bufferPtr = buffer)
            Console.WriteLine($"Array base: 0x{bufferPtr:X}");
    }
}

Memory Allocation Techniques

Stack Allocation uses stackalloc for temporary, non-garbage-collected memory on the stack. Memory is automatically released when the method exits.

unsafe class StackMemoryDemo
{
    public static void Main()
    {
        int* sequence = stackalloc int[10];
        sequence[0] = sequence[1] = 1;
        
        for (int i = 2; i < 10; i++)
            sequence[i] = sequence[i-1] + sequence[i-2];
        
        for (int i = 0; i < 10; i++)
            Console.WriteLine(sequence[i]);
    }
}

Heap Allocation requires manual management via platform invoke (P/Invoke) to access Windows API functions like HeapAlloc and HeapFree.

using System;
using System.Runtime.InteropServices;

unsafe class HeapMemoryManager
{
    const int HEAP_ZERO_MEMORY = 0x00000008;
    [DllImport("kernel32")] static extern IntPtr GetProcessHeap();
    [DllImport("kernel32")] static extern IntPtr HeapAlloc(IntPtr hHeap, uint flags, uint size);
    [DllImport("kernel32")] static extern bool HeapFree(IntPtr hHeap, uint flags, IntPtr mem);

    static readonly IntPtr heapHandle = GetProcessHeap();

    public static IntPtr Allocate(uint size)
    {
        IntPtr memory = HeapAlloc(heapHandle, HEAP_ZERO_MEMORY, size);
        if (memory == IntPtr.Zero) throw new OutOfMemoryException();
        return memory;
    }

    public static void Free(IntPtr memory)
    {
        if (!HeapFree(heapHandle, 0, memory))
            throw new InvalidOperationException("Memory deallocation failed");
    }
}

class Program
{
    unsafe static void Main()
    {
        IntPtr buffer = HeapMemoryManager.Allocate(1024);
        byte* bytePtr = (byte*)buffer;
        
        for (int i = 0; i < 1024; i++)
            bytePtr[i] = (byte)i;
        
        for (int i = 0; i < 10; i++)
            Console.WriteLine(bytePtr[i]);
        
        HeapMemoryManager.Free(buffer);
    }
}

Tags: C# Unsafe Code pointers Memory Management P/Invoke

Posted on Tue, 08 Sep 2026 16:09:39 +0000 by musicbase