Skip to content

C# Pointer Arithmetic — Complete Guide

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about C# Pointer Arithmetic. We cover key concepts, practical examples, and best practices.

You have a pointer to the start of a buffer and need to navigate to specific offsets — reading a header, parsing a binary format, or scanning memory. You add offsets manually. Pointer arithmetic lets you navigate by adding or subtracting from the pointer directly.

Wrong

unsafe void ParseBuffer(byte* buffer, int length)
{
    // Manual offset calculation
    byte type = buffer[0];
    int size = *(int*)(buffer + 1);
    byte* data = buffer + 5;
}

Output: Works, but magic numbers everywhere. Hard to read and maintain.

unsafe void ParseBuffer(byte* buffer, int length)
{
    byte* ptr = buffer;
    byte type = *ptr++;       // Read and advance
    int size = *(int*)ptr;    // Read 4 bytes at current position
    ptr += 4;                 // Advance 4 bytes
    byte* data = ptr;         // Remaining data
}

Output: Cleaner navigation. Each operation advances the pointer.

Pointer arithmetic respects the element size:

int* intPtr = (int*)buffer;
int first = *intPtr;          // First int
int second = *(intPtr + 1);   // Second int (4 bytes ahead)
intPtr += 10;                 // Advance 10 ints (40 bytes)

The difference between two pointers gives the element count:

long count = ptr2 - ptr1; // Number of elements between pointers

Prevention

  • Use pointer arithmetic for navigating binary data structures.
  • Use ++, --, +, - for pointer movement (respects element size).
  • Use *ptr for dereferencing (reading the value at the pointer).
  • Use ptr[index] as an alternative to *(ptr + index).
  • Use Span<T> and Memory<T> instead of raw pointers when possible.
  • Always check bounds before pointer arithmetic — no automatic bounds checking.
  • Be careful with void* — it has no element size, so arithmetic is not allowed.

Common Mistakes with pointer arithmetic

  1. Using foldl instead of foldl' causing stack overflow on large lists
  2. Forgetting deriving (Show, Eq) on custom data types needed for debugging
  3. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable

These mistakes appear frequently in real-world CSHARP code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

What is the size increment for pointer arithmetic?

Pointer arithmetic uses the size of the pointed-to type. byte* + 1 advances by 1 byte. int* + 1 advances by 4 bytes. long* + 1 advances by 8 bytes. This matches C/C++ pointer arithmetic semantics.

Can I do arithmetic on void*?

No. void* has no size, so arithmetic is not defined. Cast to byte* first: (byte*)voidPtr + offset. Use byte* for byte-level navigation.

What happens if I go out of bounds with pointer arithmetic?

Undefined behavior. You may corrupt memory, crash with an access violation, or silently corrupt data. No bounds checking is performed. Always validate offsets against known buffer sizes before dereferencing.

Pointer arithmetic is used in Durga Antivirus Pro's real-time scanner for fast memory pattern matching. For more C#, visit DodaTech.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro