C#
IntPtr
byte array
programming
coding tips

How to get IntPtr from byte in C

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

The phrase "get IntPtr from byte" can describe two very different tasks in C#. You might want a pointer-sized numeric value that happens to equal a byte, or you might actually need a memory pointer to byte data for interop with unmanaged code.

A Numeric byte to IntPtr

If you only want the numeric value stored in an IntPtr, use the constructor directly.

csharp
1using System;
2
3class Program
4{
5    static void Main()
6    {
7        byte value = 42;
8        IntPtr ptrValue = new IntPtr(value);
9        Console.WriteLine(ptrValue);
10    }
11}

This does not allocate memory and does not point to a byte buffer. It simply creates a pointer-sized integer whose value is 42.

That is occasionally useful when an API uses IntPtr as a general native-sized integer, but it is not a pointer to managed data.

Getting a Pointer to a byte[]

If your real goal is to pass bytes to unmanaged code, you need a real memory address. One common approach is to allocate unmanaged memory and copy the bytes into it.

csharp
1using System;
2using System.Runtime.InteropServices;
3
4class Program
5{
6    static void Main()
7    {
8        byte[] data = { 1, 2, 3, 4 };
9        IntPtr ptr = Marshal.AllocHGlobal(data.Length);
10
11        try
12        {
13            Marshal.Copy(data, 0, ptr, data.Length);
14            Console.WriteLine($"Pointer: {ptr}");
15        }
16        finally
17        {
18            Marshal.FreeHGlobal(ptr);
19        }
20    }
21}

This creates a separate unmanaged buffer. That is the safe and explicit pattern when native code needs the bytes to live outside the .NET managed heap.

Pinning an Existing Managed Array

If the unmanaged call is short-lived, you may not need to copy the data at all. You can pin the managed array so the garbage collector does not move it while the pointer is in use.

csharp
1using System;
2using System.Runtime.InteropServices;
3
4class Program
5{
6    static void Main()
7    {
8        byte[] data = { 10, 20, 30, 40 };
9        GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
10
11        try
12        {
13            IntPtr ptr = handle.AddrOfPinnedObject();
14            Console.WriteLine($"Pinned pointer: {ptr}");
15        }
16        finally
17        {
18            handle.Free();
19        }
20    }
21}

Pinning avoids a copy, but it should be used carefully. Long-lived pinned objects can make garbage collection less efficient.

unsafe Code for a Temporary Pointer

Another option is unsafe code with the fixed keyword. This is common in low-level interop and high-performance code when you want a short-lived pointer to the array contents.

csharp
1using System;
2
3class Program
4{
5    static unsafe void Main()
6    {
7        byte[] data = { 5, 6, 7, 8 };
8
9        fixed (byte* p = data)
10        {
11            IntPtr ptr = (IntPtr)p;
12            Console.WriteLine(ptr);
13        }
14    }
15}

This works well for tight native-call scopes, but it requires the project to allow unsafe code.

Pick the Right Technique for the API

The correct answer depends on what the native API expects:

  • if it expects an integer-like handle, new IntPtr(byteValue) may be enough
  • if it expects a pointer to bytes during one immediate call, pinning may be appropriate
  • if it expects the buffer to outlive the current managed scope, allocate unmanaged memory

Interop bugs happen when these cases are confused with each other.

Common Pitfalls

Treating new IntPtr(byteValue) as though it created memory containing that byte is the most common mistake.

Passing a pointer to managed memory after the pin has ended can produce invalid memory access.

Allocating unmanaged memory without freeing it causes leaks, especially in repeated interop calls.

Copying bytes into unmanaged memory is unnecessary overhead when the native API only needs a pointer during one short synchronous call.

Solving a numeric-conversion problem as though it were a buffer-pointer problem often leads to overcomplicated code.

Summary

  • 'new IntPtr(byteValue) creates a pointer-sized numeric value, not a buffer.'
  • Use unmanaged allocation when native code needs a real byte buffer outside the managed heap.
  • Use pinning or fixed for short-lived pointers to an existing managed byte[].
  • Match the pointer lifetime to what the unmanaged API expects.
  • Be explicit about ownership and cleanup when interop code allocates memory.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.