c# pointers vs IntPtr

The CLI distinguishes between managed and unmanaged pointers. A managed pointer is typed, the type of the pointed-to value is known by the runtime and only type-safe assignments are allowed. Unmanaged pointers are only directly usable in a language that supports them, C++/CLI is the best example.

The equivalent of an unmanaged pointer in the C# language is IntPtr. You can freely convert a pointer back and forth with a cast. No pointer type is associated with it even though its name sounds like "pointer to int", it is the equivalent of void* in C/C++. Using such a pointer requires pinvoke, the Marshal class or a cast to a managed pointer type.

Some code to play with:

using System;
using System.Runtime.InteropServices;

unsafe class Program {
    static void Main(string[] args) {
        int variable = 42;
        int* p = &variable;
        Console.WriteLine(*p);
        IntPtr raw = (IntPtr)p;
        Marshal.WriteInt32(raw, 666);
        p = (int*)raw;
        Console.WriteLine(*p);
        Console.ReadLine();
    }
}

Note how the unsafe keyword is appropriate here. You can call Marshal.WriteInt64() and you get no complaint whatsoever. It corrupts the stack frame.


An IntPtr can't be used as a replacement for a pointer.

The IntPtr just contains a numerical value, so you can't use it to access any data. Hence the name; it's an integer value with the same size as a pointer. You need to turn the value into a pointer to access the data that it points to, so there is no way to access the data without using unsafe code.

Note also that IntPtr is a structure, not an object, so the garbage collector isn't directly concerned with it at all.


IntPtr is a managed object but the object it is pointing to is still not garbage collected. Using unsafe pointers in C# is really something that you should avoid. Code using unsafe pointers might not account for differences in memory addresses between x86 and x64 systems. It allows you to directly manipulate memory addresses easily which is not the case with IntPtr as you would need to marshal between the pointer and the actual structure stored at this memory address. With unsafe pointers you could directly work with the underlying type: here's a blog post I wrote illustrating one possible use of unsafe pointers. Another common example is manipulating image pixels directly.

Tags:

C#

.Net

Pointers