C#idiomatic C#
stackalloccsharp/language-reference/operators

Language

stackalloc expression (C# reference)

The C# stackalloc expression allocates a block of memory on the stack. Stackalloc memory is automatically discarded when that method returns.

  • page csharp/language-reference/operators/stackalloc
  • updated 06/16/2026

A stackalloc expression allocates a block of memory on the stack. A stack-allocated memory block created during the method execution is automatically discarded when that method returns. You can't explicitly free the memory allocated by stackalloc. A stack-allocated memory block isn't subject to garbage collection and doesn't need to be pinned by a fixed statement.


ms.custom: "updateeachrelease"

The C# language reference documents the most recently released version of the C# language. It also contains initial documentation for features in public previews for the upcoming language release.

The documentation identifies any feature first introduced in the last three versions of the language or in current public previews.

You can assign the result of a stackalloc expression to a variable of one of the following types:

sample · csharpdocs/csharp/language-reference/operators/snippets/shared/StackallocOperator.csAssignToSpan

csharp
namespace operators;

public static class StackallocOperator
{
    public static void Examples()
    {
        StackallocInNestedExpressions();
    }

    private static void AssignToPointer()
    {
        // <SnippetAssignToPointer>
        unsafe
        {
            int length = 3;
            int* numbers = stackalloc int[length];
            for (var i = 0; i < length; i++)
            {
                numbers[i] = i;
            }
        }
        // </SnippetAssignToPointer>
    }

    private static void AssignToSpan()
    {
        // <SnippetAssignToSpan>
        int length = 3;
        Span<int> numbers = stackalloc int[length];
        for (var i = 0; i < length; i++)
        {
            numbers[i] = i;
        }
        // </SnippetAssignToSpan>
    }

    private static void AsExpression()
    {
        // <SnippetAsExpression>
        int length = 1000;
        Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];
        // </SnippetAsExpression>
    }

    private static void StackallocInit()
    {
        // <SnippetStackallocInit>
        Span<int> first = stackalloc int[3] { 1, 2, 3 };
        Span<int> second = stackalloc int[] { 1, 2, 3 };
        ReadOnlySpan<int> third = stackalloc[] { 1, 2, 3 };

        // Using collection expressions:
        Span<int> fourth = [1, 2, 3];
        ReadOnlySpan<int> fifth = [1, 2, 3];
        // </SnippetStackallocInit>
    }

    private static void StackallocInNestedExpressions()
    {
        // <SnippetNested>
        Span<int> numbers = stackalloc[] { 1, 2, 3, 4, 5, 6 };
        var ind = numbers.IndexOfAny(stackalloc[] { 2, 4, 6, 8 });
        Console.WriteLine(ind);  // output: 1

        Span<int> numbers2 = [1, 2, 3, 4, 5, 6];
        var ind2 = numbers2.IndexOfAny([2, 4, 6, 8]);
        Console.WriteLine(ind2);  // output: 1
        // </SnippetNested>
    }

    private static void LimitStackAllocatedMemory(int inputLength)
    {
        // <SnippetLimitStackalloc>
        const int MaxStackLimit = 1024;
        Span<byte> buffer = inputLength <= MaxStackLimit ? stackalloc byte[inputLength] : new byte[inputLength];
        // </SnippetLimitStackalloc>
    }
}

You don't need to use an unsafe context when you assign a stack-allocated memory block to a System.Span or System.ReadOnlySpan variable.

When you work with those types, you can use a stackalloc expression in conditional or assignment expressions, as the following example shows:

sample · csharpdocs/csharp/language-reference/operators/snippets/shared/StackallocOperator.csAsExpression

csharp
namespace operators;

public static class StackallocOperator
{
    public static void Examples()
    {
        StackallocInNestedExpressions();
    }

    private static void AssignToPointer()
    {
        // <SnippetAssignToPointer>
        unsafe
        {
            int length = 3;
            int* numbers = stackalloc int[length];
            for (var i = 0; i < length; i++)
            {
                numbers[i] = i;
            }
        }
        // </SnippetAssignToPointer>
    }

    private static void AssignToSpan()
    {
        // <SnippetAssignToSpan>
        int length = 3;
        Span<int> numbers = stackalloc int[length];
        for (var i = 0; i < length; i++)
        {
            numbers[i] = i;
        }
        // </SnippetAssignToSpan>
    }

    private static void AsExpression()
    {
        // <SnippetAsExpression>
        int length = 1000;
        Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];
        // </SnippetAsExpression>
    }

    private static void StackallocInit()
    {
        // <SnippetStackallocInit>
        Span<int> first = stackalloc int[3] { 1, 2, 3 };
        Span<int> second = stackalloc int[] { 1, 2, 3 };
        ReadOnlySpan<int> third = stackalloc[] { 1, 2, 3 };

        // Using collection expressions:
        Span<int> fourth = [1, 2, 3];
        ReadOnlySpan<int> fifth = [1, 2, 3];
        // </SnippetStackallocInit>
    }

    private static void StackallocInNestedExpressions()
    {
        // <SnippetNested>
        Span<int> numbers = stackalloc[] { 1, 2, 3, 4, 5, 6 };
        var ind = numbers.IndexOfAny(stackalloc[] { 2, 4, 6, 8 });
        Console.WriteLine(ind);  // output: 1

        Span<int> numbers2 = [1, 2, 3, 4, 5, 6];
        var ind2 = numbers2.IndexOfAny([2, 4, 6, 8]);
        Console.WriteLine(ind2);  // output: 1
        // </SnippetNested>
    }

    private static void LimitStackAllocatedMemory(int inputLength)
    {
        // <SnippetLimitStackalloc>
        const int MaxStackLimit = 1024;
        Span<byte> buffer = inputLength <= MaxStackLimit ? stackalloc byte[inputLength] : new byte[inputLength];
        // </SnippetLimitStackalloc>
    }
}

You can use a stackalloc expression or a collection expression inside other expressions whenever a System.Span or System.ReadOnlySpan variable is allowed, as the following example shows:

sample · csharpdocs/csharp/language-reference/operators/snippets/shared/StackallocOperator.csNested

csharp
namespace operators;

public static class StackallocOperator
{
    public static void Examples()
    {
        StackallocInNestedExpressions();
    }

    private static void AssignToPointer()
    {
        // <SnippetAssignToPointer>
        unsafe
        {
            int length = 3;
            int* numbers = stackalloc int[length];
            for (var i = 0; i < length; i++)
            {
                numbers[i] = i;
            }
        }
        // </SnippetAssignToPointer>
    }

    private static void AssignToSpan()
    {
        // <SnippetAssignToSpan>
        int length = 3;
        Span<int> numbers = stackalloc int[length];
        for (var i = 0; i < length; i++)
        {
            numbers[i] = i;
        }
        // </SnippetAssignToSpan>
    }

    private static void AsExpression()
    {
        // <SnippetAsExpression>
        int length = 1000;
        Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];
        // </SnippetAsExpression>
    }

    private static void StackallocInit()
    {
        // <SnippetStackallocInit>
        Span<int> first = stackalloc int[3] { 1, 2, 3 };
        Span<int> second = stackalloc int[] { 1, 2, 3 };
        ReadOnlySpan<int> third = stackalloc[] { 1, 2, 3 };

        // Using collection expressions:
        Span<int> fourth = [1, 2, 3];
        ReadOnlySpan<int> fifth = [1, 2, 3];
        // </SnippetStackallocInit>
    }

    private static void StackallocInNestedExpressions()
    {
        // <SnippetNested>
        Span<int> numbers = stackalloc[] { 1, 2, 3, 4, 5, 6 };
        var ind = numbers.IndexOfAny(stackalloc[] { 2, 4, 6, 8 });
        Console.WriteLine(ind);  // output: 1

        Span<int> numbers2 = [1, 2, 3, 4, 5, 6];
        var ind2 = numbers2.IndexOfAny([2, 4, 6, 8]);
        Console.WriteLine(ind2);  // output: 1
        // </SnippetNested>
    }

    private static void LimitStackAllocatedMemory(int inputLength)
    {
        // <SnippetLimitStackalloc>
        const int MaxStackLimit = 1024;
        Span<byte> buffer = inputLength <= MaxStackLimit ? stackalloc byte[inputLength] : new byte[inputLength];
        // </SnippetLimitStackalloc>
    }
}

sample · csharpdocs/csharp/language-reference/operators/snippets/shared/StackallocOperator.csAssignToPointer

csharp
namespace operators;

public static class StackallocOperator
{
    public static void Examples()
    {
        StackallocInNestedExpressions();
    }

    private static void AssignToPointer()
    {
        // <SnippetAssignToPointer>
        unsafe
        {
            int length = 3;
            int* numbers = stackalloc int[length];
            for (var i = 0; i < length; i++)
            {
                numbers[i] = i;
            }
        }
        // </SnippetAssignToPointer>
    }

    private static void AssignToSpan()
    {
        // <SnippetAssignToSpan>
        int length = 3;
        Span<int> numbers = stackalloc int[length];
        for (var i = 0; i < length; i++)
        {
            numbers[i] = i;
        }
        // </SnippetAssignToSpan>
    }

    private static void AsExpression()
    {
        // <SnippetAsExpression>
        int length = 1000;
        Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];
        // </SnippetAsExpression>
    }

    private static void StackallocInit()
    {
        // <SnippetStackallocInit>
        Span<int> first = stackalloc int[3] { 1, 2, 3 };
        Span<int> second = stackalloc int[] { 1, 2, 3 };
        ReadOnlySpan<int> third = stackalloc[] { 1, 2, 3 };

        // Using collection expressions:
        Span<int> fourth = [1, 2, 3];
        ReadOnlySpan<int> fifth = [1, 2, 3];
        // </SnippetStackallocInit>
    }

    private static void StackallocInNestedExpressions()
    {
        // <SnippetNested>
        Span<int> numbers = stackalloc[] { 1, 2, 3, 4, 5, 6 };
        var ind = numbers.IndexOfAny(stackalloc[] { 2, 4, 6, 8 });
        Console.WriteLine(ind);  // output: 1

        Span<int> numbers2 = [1, 2, 3, 4, 5, 6];
        var ind2 = numbers2.IndexOfAny([2, 4, 6, 8]);
        Console.WriteLine(ind2);  // output: 1
        // </SnippetNested>
    }

    private static void LimitStackAllocatedMemory(int inputLength)
    {
        // <SnippetLimitStackalloc>
        const int MaxStackLimit = 1024;
        Span<byte> buffer = inputLength <= MaxStackLimit ? stackalloc byte[inputLength] : new byte[inputLength];
        // </SnippetLimitStackalloc>
    }
}

You must use an unsafe context when you work with pointer types.

For pointer types, you can use a stackalloc expression only in a local variable declaration to initialize the variable.

The amount of memory available on the stack is limited. If you allocate too much memory on the stack, a System.StackOverflowException is thrown. To avoid that exception, follow these rules:

  • Limit the amount of memory you allocate by using stackalloc. For example, if the intended buffer size is below a certain limit, allocate the memory on the stack. Otherwise, use an array of the required length, as the following code shows:

sample · csharpdocs/csharp/language-reference/operators/snippets/shared/StackallocOperator.csLimitStackalloc

csharp
namespace operators;

public static class StackallocOperator
{
    public static void Examples()
    {
        StackallocInNestedExpressions();
    }

    private static void AssignToPointer()
    {
        // <SnippetAssignToPointer>
        unsafe
        {
            int length = 3;
            int* numbers = stackalloc int[length];
            for (var i = 0; i < length; i++)
            {
                numbers[i] = i;
            }
        }
        // </SnippetAssignToPointer>
    }

    private static void AssignToSpan()
    {
        // <SnippetAssignToSpan>
        int length = 3;
        Span<int> numbers = stackalloc int[length];
        for (var i = 0; i < length; i++)
        {
            numbers[i] = i;
        }
        // </SnippetAssignToSpan>
    }

    private static void AsExpression()
    {
        // <SnippetAsExpression>
        int length = 1000;
        Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];
        // </SnippetAsExpression>
    }

    private static void StackallocInit()
    {
        // <SnippetStackallocInit>
        Span<int> first = stackalloc int[3] { 1, 2, 3 };
        Span<int> second = stackalloc int[] { 1, 2, 3 };
        ReadOnlySpan<int> third = stackalloc[] { 1, 2, 3 };

        // Using collection expressions:
        Span<int> fourth = [1, 2, 3];
        ReadOnlySpan<int> fifth = [1, 2, 3];
        // </SnippetStackallocInit>
    }

    private static void StackallocInNestedExpressions()
    {
        // <SnippetNested>
        Span<int> numbers = stackalloc[] { 1, 2, 3, 4, 5, 6 };
        var ind = numbers.IndexOfAny(stackalloc[] { 2, 4, 6, 8 });
        Console.WriteLine(ind);  // output: 1

        Span<int> numbers2 = [1, 2, 3, 4, 5, 6];
        var ind2 = numbers2.IndexOfAny([2, 4, 6, 8]);
        Console.WriteLine(ind2);  // output: 1
        // </SnippetNested>
    }

    private static void LimitStackAllocatedMemory(int inputLength)
    {
        // <SnippetLimitStackalloc>
        const int MaxStackLimit = 1024;
        Span<byte> buffer = inputLength <= MaxStackLimit ? stackalloc byte[inputLength] : new byte[inputLength];
        // </SnippetLimitStackalloc>
    }
}
  • Avoid using stackalloc inside loops. Allocate the memory block outside a loop and reuse it inside the loop.

The content of the newly allocated memory is undefined. You should initialize it before it's used, either with a stackalloc initializer or a method like System.Span.Clear.

You can use array initializer syntax to define the content of the newly allocated memory. The following example demonstrates various ways to do that:

sample · csharpdocs/csharp/language-reference/operators/snippets/shared/StackallocOperator.csStackallocInit

csharp
namespace operators;

public static class StackallocOperator
{
    public static void Examples()
    {
        StackallocInNestedExpressions();
    }

    private static void AssignToPointer()
    {
        // <SnippetAssignToPointer>
        unsafe
        {
            int length = 3;
            int* numbers = stackalloc int[length];
            for (var i = 0; i < length; i++)
            {
                numbers[i] = i;
            }
        }
        // </SnippetAssignToPointer>
    }

    private static void AssignToSpan()
    {
        // <SnippetAssignToSpan>
        int length = 3;
        Span<int> numbers = stackalloc int[length];
        for (var i = 0; i < length; i++)
        {
            numbers[i] = i;
        }
        // </SnippetAssignToSpan>
    }

    private static void AsExpression()
    {
        // <SnippetAsExpression>
        int length = 1000;
        Span<byte> buffer = length <= 1024 ? stackalloc byte[length] : new byte[length];
        // </SnippetAsExpression>
    }

    private static void StackallocInit()
    {
        // <SnippetStackallocInit>
        Span<int> first = stackalloc int[3] { 1, 2, 3 };
        Span<int> second = stackalloc int[] { 1, 2, 3 };
        ReadOnlySpan<int> third = stackalloc[] { 1, 2, 3 };

        // Using collection expressions:
        Span<int> fourth = [1, 2, 3];
        ReadOnlySpan<int> fifth = [1, 2, 3];
        // </SnippetStackallocInit>
    }

    private static void StackallocInNestedExpressions()
    {
        // <SnippetNested>
        Span<int> numbers = stackalloc[] { 1, 2, 3, 4, 5, 6 };
        var ind = numbers.IndexOfAny(stackalloc[] { 2, 4, 6, 8 });
        Console.WriteLine(ind);  // output: 1

        Span<int> numbers2 = [1, 2, 3, 4, 5, 6];
        var ind2 = numbers2.IndexOfAny([2, 4, 6, 8]);
        Console.WriteLine(ind2);  // output: 1
        // </SnippetNested>
    }

    private static void LimitStackAllocatedMemory(int inputLength)
    {
        // <SnippetLimitStackalloc>
        const int MaxStackLimit = 1024;
        Span<byte> buffer = inputLength <= MaxStackLimit ? stackalloc byte[inputLength] : new byte[inputLength];
        // </SnippetLimitStackalloc>
    }
}

In expression stackalloc T[E], T must be an unmanaged type and E must evaluate to a non-negative int value. When you use the collection expression syntax to initialize the span, the compiler can use stack-allocated storage for a span if it doesn't violate ref safety.

Security

Using stackalloc automatically turns on buffer overrun detection features in the common language runtime (CLR). If the runtime detects a buffer overrun, it terminates the process as quickly as possible to reduce the chance that malicious code runs.

C# language specification

For more information, see the Stack allocation section of the C# language specification.

See also