Follow a pointer relative to an origin
Advanced · C#. Pointer width, field position, stored address, and effective target are different concepts. The options bound this example to one pointer level and one target byte.
Run this example
Prerequisites: the repository's .NET 10 SDK and a checkout of this source. Run from the repository root:
dotnet run --project docs/examples/CStructSharp.Docs.Examples.csproj -c Release -- relative-pointer
The runner checks stored address 1 plus origin 1 reaches offset 2 and value 42. Success includes PASS relative-pointer.
This example uses the C# API. Browser capabilities and result shapes are described in the browser guide.
Complete program
The layout, options, input bytes, helper methods, and required types are all included. To adapt it outside the repository, create a .NET 10 console project, add CStructSharp, and replace Program.cs with this complete file. These examples follow the source version; use a matching package when testing a release.
Download the complete C# source.
// Generated from executable documentation examples. Edit the source region, then regenerate.
using System;
using System.IO;
using System.IO.Pipelines;
using System.Linq;
using System.Buffers;
using System.Collections.Generic;
using System.Dynamic;
using System.Globalization;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using CStructSharp;
using CStructSharp.Codecs;
using CStructSharp.Diagnostics;
using CStructSharp.Introspection;
using CStructSharp.Values;
internal static partial class Program
{
public static void Main()
{
RelativePointer();
Console.WriteLine("PASS relative-pointer");
}
private static void RelativePointer()
{
var layout = new CStruct("struct root { uint8 *target; };", pointerSize: 1);
byte[] bytes = [0xEE, 1, 42];
using var stream = new MemoryStream(bytes);
stream.Position = 1;
StructValue root = layout.Parse(stream, "root", options: new ReadOptions
{
AddressingMode = PointerAddressingMode.Relative,
Origin = 1,
MaxPointerDepth = 1,
MaxPointerTargetBytes = 1,
});
Pointer pointer = root.Get<Pointer>("target");
Equal(1L, pointer.Address);
Equal((byte)42, (byte)pointer.Value!);
}
private static void Equal<T>(T expected, T actual)
{
if (!EqualityComparer<T>.Default.Equals(expected, actual))
{
throw new InvalidOperationException($"Expected '{expected}', received '{actual}'.");
}
}
}
Try it and diagnose mistakes
Set origin to 0 and predict the target.
Answer: The target becomes offset 1. It is a valid position but does not contain the intended value. The program contains assertions for its original inputs. When changing an input intentionally, update the expected assertion too; an unchanged assertion is not evidence that the new value is wrong.
Continue with the related guide or choose another recipe.