Through using IntelliSense and looking at other people's code, I have come across this IntPtr
type; every time it has needed to be used I have simply put null
or IntPtr.Zero
and found most functions to work. What exactly is it and when/why is it used?

- 15,630
- 17
- 67
- 90
8 Answers
It's a "native (platform-specific) size integer." It's internally represented as void*
but exposed as an integer. You can use it whenever you need to store an unmanaged pointer and don't want to use unsafe
code. IntPtr.Zero
is effectively NULL
(a null pointer).

- 97,721
- 20
- 209
- 280
-
56A pointer is something that points to an address in memory. In managed languages you have references (the address can move around) while in unmanaged languages you have pointers (the address is fixed) – Colin Mackay Jul 18 '09 at 18:24
-
97In general (across programming languages), a pointer is a number that represents a physical location in memory. A *null* pointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. – Sam Harwell Jul 18 '09 at 18:24
-
5+1 for that comment @280Z28, that is the most succinct explanation of pointers I've ever seen. – BlueRaja - Danny Pflughoeft Dec 13 '10 at 23:38
-
1I've always thought it was a mistake from MS part naming this type like this. As you said it's designed to be a platform-specific integer, and as a consequence they're good to store pointer addresses. A better and less confusing name would have been something along the lines of 'PlatformSpecificInt', 'PSInt' and the such, but not 'Ptr'. – Trap May 30 '12 at 10:32
-
Maybe it'd be better if they described it as "Integer Pointer" – Interarticle Jun 30 '12 at 14:49
-
9It's called IntPtr, because to use it from unmanaged native code, C/C++, you will have to use the analogic type: intptr_t. C#'s IntPtr maps exactly to C/C++'s intptr_t. And it's probably implemented as intptr_t. In C/C++, intptr_t type is guaranteed to be the same size as void* type. – Петър Петров Apr 01 '15 at 10:36
-
2@Trap "A platform-specific type that is used to represent a pointer or a handle." Not a "platform-specific integer", a "platform-specific way to represent a pointer or a handle". `IntPtr` makes perfect sense, because it's an integer (as in mathematical integer) and a pointer (as in pointer). The `Int` part has little to do with the int type - it's a concept, not a specific type. Though to be fair, the only thing the CLI spec says about it is that it is indeed an "Integer, native size". Oh well :) – Luaan Sep 14 '16 at 12:46
-
by memory are we meaning RAM here? – Md Sifatul Islam Nov 17 '16 at 10:40
-
It is also represenation of `nint`. See [nint and nuint types (C# reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nint-nuint). – Yarl Jun 19 '21 at 16:25
It's a value type large enough to store a memory address as used in native or unsafe code, but not directly usable as a memory address in safe managed code.
You can use IntPtr.Size
to find out whether you're running in a 32-bit or 64-bit process, as it will be 4 or 8 bytes respectively.

- 7,243
- 6
- 49
- 61

- 114,894
- 38
- 205
- 284
-
17Good point about detecting the size of address space for the process. – Noldorin Jul 18 '09 at 18:20
-
@Noldorin True, but not necessarily reliable. In the past, there have been plenty of architectures that had multiple pointer types, and on Windows, `IntPtr` is also used to represent handles which are 32-bit regardless of architecture (though `Size` still says 8 in that case). The CLI spec only notes that it's an integer that is of "native size", but that doesn't say much, really. – Luaan Sep 14 '16 at 12:46
-
@Luaan that doesn't really change anything in my answer does it? IntPtr is so called (and is used throughout CLR source) as a value large enough to hold a memory address. It can hold smaller values of course. Some architectures have multiple pointer types, but must have one that is the largest of the set. – Daniel Earwicker Sep 14 '16 at 13:07
-
@DanielEarwicker Well, it's not a problem with any current .NET implementation, as far as I'm aware. However, the (historical) issue isn't just about size - the various pointers may be entirely incompatible. In an example closer to today, PAE would use 64-bit addresses even though the "native pointer size" was still 32-bit. It goes all the way back to the argument "what does '32-bit system' mean, really?" We have 256-bit and 512-bit numerical registers now, but still call it 64-bit. Even though you *can't* actually address 64-bits of physical memory with your 64-bit "pointers". It's a mess. – Luaan Sep 14 '16 at 14:18
-
1Some of it's complicated, but IntPtr is still "a value type large enough to store a memory address". It's not as large as the largest hardware register, to take one of your examples. That's just not what it's for. It's large enough to represent a memory address. Then there's stuff like this: http://stackoverflow.com/questions/12006854/why-the-size-of-a-pointer-to-a-function-is-different-from-the-size-of-a-pointer where we have the word "pointer" being used for something other than a memory address - which is why I specifically said "memory address". – Daniel Earwicker Sep 14 '16 at 14:52
Here's an example:
I'm writing a C# program that interfaces with a high-speed camera. The camera has its own driver that acquires images and loads them into the computer's memory for me automatically.
So when I'm ready to bring the latest image into my program to work with, the camera driver provides me with an IntPtr to where the image is ALREADY stored in physical memory, so I don't have to waste time/resources creating another block of memory to store an image that's in memory already. The IntPtr just shows me where the image already is.
-
8So the IntPtr simple allows you to use an unmanaged pointer (like that used in your camera driver) in managed code? – Callum Rogers Jul 18 '09 at 22:34
-
6Yes. Well in this case, most likely the camera driver uses unmanaged drivers under the hood, but in order to operate properly in the Managed-only world it provides the IntPtr to allow me to work with the data safely. – bufferz Jul 19 '09 at 00:21
-
4So why wouldn't it just give you back a stream (byte array)? Why is it unsafe or unable to return the value? – The Muffin Man May 09 '14 at 04:36
A direct interpretation
An IntPtr is an integer which is the same size as a pointer.
You can use IntPtr to store a pointer value in a non-pointer type. This feature is important in .NET since using pointers is highly error prone and therefore illegal in most contexts. By allowing the pointer value to be stored in a "safe" data type, plumbing between unsafe code segments may be implemented in safer high-level code -- or even in a .NET language that doesn't directly support pointers.
The size of IntPtr is platform-specific, but this detail rarely needs to be considered, since the system will automatically use the correct size.
The name "IntPtr" is confusing -- something like Handle
might have been more appropriate. My initial guess was that "IntPtr" was a pointer to an integer. The MSDN documentation of IntPtr goes into somewhat cryptic detail without ever providing much insight about the meaning of the name.
An alternative perspective
An IntPtr
is a pointer with two limitations:
- It cannot be directly dereferenced
- It doesn't know the type of the data that it points to.
In other words, an IntPtr
is just like a void*
-- but with the extra feature that it can (but shouldn't) be used for basic pointer arithmetic.
In order to dereference an IntPtr
, you can either cast it to a true pointer (an operation which can only be performed in "unsafe" contexts) or you can pass it to a helper routine such as those provided by the InteropServices.Marshal
class. Using the Marshal
class gives the illusion of safety since it doesn't require you to be in an explicit "unsafe" context. However, it doesn't remove the risk of crashing which is inherent in using pointers.

- 1
- 1

- 51,587
- 17
- 154
- 173
-
2There is some precedent for the name "intptr" from the C99 standard of the "C" programming language. http://linux.die.net/man/3/intptr_t. – Brent Bradburn Jan 10 '10 at 03:32
What is a Pointer?
In all languages, a pointer is a type of variable that stores a memory address, and you can either ask them to tell you the address they are pointing at or the value at the address they are pointing at.
A pointer can be thought of as a sort-of book mark. Except, instead of being used to jump quickly to a page in a book, a pointer is used to keep track of or map blocks of memory.
Imagine your program's memory precisely like one big array of 65535 bytes.
Pointers point obediently
Pointers remember one memory address each, and therefore they each point to a single address in memory.
As a group, pointers remember and recall memory addresses, obeying your every command ad nauseum.
You are their king.
Pointers in C#
Specifically in C#, a pointer is an integer variable that stores a memory address between 0 and 65534.
Also specific to C#, pointers are of type int and therefore signed.
You can't use negatively numbered addresses though, neither can you access an address above 65534. Any attempt to do so will throw a System.AccessViolationException.
A pointer called MyPointer is declared like so:
int *MyPointer;
A pointer in C# is an int, but memory addresses in C# begin at 0 and extend as far as 65534.
Pointy things should be handled with extra special care
The word unsafe is intended to scare you, and for a very good reason: Pointers are pointy things, and pointy things e.g. swords, axes, pointers, etc. should be handled with extra special care.
Pointers give the programmer tight control of a system. Therefore mistakes made are likely to have more serious consequences.
In order to use pointers, unsafe code has to be enabled in your program's properties, and pointers have to be used exclusively in methods or blocks marked as unsafe.
Example of an unsafe block
unsafe
{
// Place code carefully and responsibly here.
}
How to use Pointers
When variables or objects are declared or instantiated, they are stored in memory.
- Declare a pointer by using the * symbol prefix.
int *MyPointer;
- To get the address of a variable, you use the & symbol prefix.
MyPointer = &MyVariable;
Once an address is assigned to a pointer, the following applies:
- Without * prefix to refer to the memory address being pointed to as an int.
MyPointer = &MyVariable; // Set MyPointer to point at MyVariable
- With * prefix to get the value stored at the memory address being pointed to.
"MyPointer is pointing at " + *MyPointer;
Since a pointer is a variable that holds a memory address, this memory address can be stored in a pointer variable.
Example of pointers being used carefully and responsibly
public unsafe void PointerTest()
{
int x = 100; // Create a variable named x
int *MyPointer = &x; // Store the address of variable named x into the pointer named MyPointer
textBox1.Text = ((int)MyPointer).ToString(); // Displays the memory address stored in pointer named MyPointer
textBox2.Text = (*MyPointer).ToString(); // Displays the value of the variable named x via the pointer named MyPointer.
}
Notice the type of the pointer is an int. This is because C# interprets memory addresses as integer numbers (int).
Why is it int instead of uint?
There is no good reason.
Why use pointers?
Pointers are a lot of fun. With so much of the computer being controlled by memory, pointers empower a programmer with more control of their program's memory.
Memory monitoring.
Use pointers to read blocks of memory and monitor how the values being pointed at change over time.
Change these values responsibly and keep track of how your changes affect your computer.

- 8,539
- 4
- 63
- 74
-
5`65534` seems very wrong as a pointer range. You should provide a reference. – Brent Bradburn May 09 '18 at 13:39
-
5I voted this up because it's a great article explaining pointers. I would like to see some references to the specs you've mentioned (as commented above). However; this answer has nothing to do with the question. The question was about ```System.IntPtr```. I would like to see the answer updated at the end explaining what also an ```System.IntPtr``` and how it relates to unsafe pointers in C# please. – Michael Puckett II Jan 13 '19 at 14:42
-
”Notice the type of the pointer is an int. This is because C# interprets memory addresses as integer numbers (int)." -- you might **mean** the correct thing (that C# interprets the **bits stored at the address specified by the pointer** as (possibly signed) binary representation of an integer) but you're definitely **saying** the wrong thing (that **addresses** are interpreted as integers) – Bananach Sep 19 '22 at 14:26
MSDN tells us:
The IntPtr type is designed to be an integer whose size is platform-specific. That is, an instance of this type is expected to be 32-bits on 32-bit hardware and operating systems, and 64-bits on 64-bit hardware and operating systems.
The IntPtr type can be used by languages that support pointers, and as a common means of referring to data between languages that do and do not support pointers.
IntPtr objects can also be used to hold handles. For example, instances of IntPtr are used extensively in the System.IO.FileStream class to hold file handles.
The IntPtr type is CLS-compliant, while the UIntPtr type is not. Only the IntPtr type is used in the common language runtime. The UIntPtr type is provided mostly to maintain architectural symmetry with the IntPtr type.
http://msdn.microsoft.com/en-us/library/system.intptr(VS.71).aspx

- 18,681
- 11
- 71
- 90
Well this is the MSDN page that deals with IntPtr
.
The first line reads:
A platform-specific type that is used to represent a pointer or a handle.
As to what a pointer or handle is the page goes on to state:
The IntPtr type can be used by languages that support pointers, and as a common means of referring to data between languages that do and do not support pointers.
IntPtr objects can also be used to hold handles. For example, instances of IntPtr are used extensively in the System.IO.FileStream class to hold file handles.
A pointer is a reference to an area of memory that holds some data you are interested in.
A handle can be an identifier for an object and is passed between methods/classes when both sides need to access that object.
An IntPtr
is a value type that is primarily used to hold memory addresses or handles. A pointer is a memory address. A pointer can be typed (e.g. int*
) or untyped (e.g. void*
). A Windows handle is a value that is usually the same size (or smaller) than a memory address and represents a system resource (like a file or window).

- 17,602
- 7
- 105
- 102