Skip to main content

How to Resolve Error "CS0213: You cannot use the fixed statement to take the address of an already fixed expression" in C#

The Compiler Error CS0213 is a redundancy error in Unsafe Code. The message reads: "You cannot use the fixed statement to take the address of an already fixed expression".

In C#, the fixed statement is used to pin a managed variable (like an array or a string) so that the Garbage Collector (GC) does not move it while you use a pointer. However, if a variable is already pinned (e.g., it is a stack-allocated variable or a pre-existing pointer), attempting to "re-pin" it using the fixed statement is redundant and invalid. The compiler flags this because the operation is unnecessary.

This guide explains which variables are naturally fixed and how to simplify your code.

Understanding Fixed vs. Movable Memory

To understand this error, you must distinguish between the two types of memory in .NET:

  • Heap Memory (Movable): Objects created with new (arrays, classes, strings). The GC moves these to optimize memory. You MUST use fixed to get a pointer to them.
  • Stack Memory (Fixed): Local variables of value types (int, struct, bool). These are allocated on the execution stack. They never move while the function is running. You DO NOT need fixed to get a pointer to them; just use &.

CS0213 happens when you treat a Stack variable or an already-pinned address as if it were a Heap object.

Scenario 1: Fixing a Local Variable (Stack Memory)

The most common mistake is applying the fixed pattern blindly to local variables. Since local variables live on the stack, they are inherently fixed.

Example of error

Trying to pin a simple integer variable.

unsafe class Program
{
static void Main()
{
int number = 42; // Lives on the Stack

// ⛔️ Error CS0213: You cannot use the fixed statement to take the address
// of an already fixed expression.
// 'number' is already fixed because it is a local stack variable.
fixed (int* p = &number)
{
*p = 100;
}
}
}

Solution: Use Address-Of Directly

You can take the address of a local variable directly without a block.

unsafe class Program
{
static void Main()
{
int number = 42;

// ✅ Correct: Just take the address. No pinning needed.
int* p = &number;

*p = 100;
System.Console.WriteLine(number); // Output: 100
}
}

Scenario 2: Fixing an Existing Pointer

If you already have a pointer (perhaps passed into your function or obtained from a previous fixed block), that pointer already represents a valid memory address. You cannot "pin" a pointer; it is just a number.

Example of error

Trying to wrap an existing pointer in a fixed block.

unsafe class ImageProcessor
{
// The method receives a pointer. The caller has typically already handled pinning.
public void InvertColors(int* pixelPtr)
{
// ⛔️ Error CS0213: 'pixelPtr' is already a pointer (an address).
// You cannot fix it again.
fixed (int* p = pixelPtr)
{
// ...
}
}
}

Solution: Use the Pointer Directly

Just use the variable as is.

unsafe class ImageProcessor
{
public void InvertColors(int* pixelPtr)
{
// ✅ Correct: Use the pointer directly.
// Note: It is the caller's responsibility to ensure the memory is valid.
int firstPixel = *pixelPtr;
}
}
note

What if I want to create a pointer alias? If you just want to rename the pointer for a block of code, simply declare a new local pointer: int* p = pixelPtr;

Conclusion

CS0213 is the compiler telling you: "You are trying to hold down something that isn't moving."

  1. Check the Source: Is the variable a local int, double, or struct?
    • If Yes: It is on the stack. Use &variable directly. Do not use fixed.
  2. Check the Type: Is the variable already a pointer (Type*)?
    • If Yes: It is already an address. Use it directly. Do not use fixed.
  3. Only use fixed for:
    • Managed Arrays (int[])
    • Strings (string)
    • Fields inside Classes (myObj.myField)