Portable and safe way to add byte offset to any pointer

Daniel A.A. Pelsmaeker picture Daniel A.A. Pelsmaeker · Apr 10, 2013 · Viewed 24k times · Source

I'm quite new at working with C++ and haven't grasped all the intricacies and subtleties of the language.

What is the most portable, correct and safe way to add an arbitrary byte offset to a pointer of any type in C++11?

SomeType* ptr;
int offset = 12345 /* bytes */;
ptr = ptr + offset;             // <--

I found many answers on Stack Overflow and Google, but they all propose different things. Some variants I have encountered:

  1. Cast to char *:

    ptr = (SomeType*)(((char*)ptr) + offset);
    
  2. Cast to unsigned int:

    ptr = (SomeType*)((unsigned int)ptr) + offset);
    
  3. Cast to size_t:

    ptr = (SomeType*)((size_t)ptr) + offset);
    
  4. "The size of size_t and ptrdiff_t always coincide with the pointer's size. Because of this, it is these types that should be used as indexes for large arrays, for storage of pointers and pointer arithmetic." - About size_t and ptrdiff_t on CodeProject

    ptr = (SomeType*)((size_t)ptr + (ptrdiff_t)offset);
    
  5. Or like the previous, but with intptr_t instead of size_t, which is signed instead of unsigned:

    ptr = (SomeType*)((intptr_t)ptr + (ptrdiff_t)offset);
    
  6. Only cast to intptr_t, since offset is already a signed integer and intptr_t is not size_t:

    ptr = (SomeType*)((intptr_t)ptr) + offset);
    

And in all these cases, is it safe to use old C-style casts, or is it safer or more portable to use static_cast or reinterpret_cast for this?

Should I assume the pointer value itself is unsigned or signed?

Answer

freddy.smith picture freddy.smith · Apr 10, 2013

I would use something like:

unsigned char* bytePtr = reinterpret_cast<unsigned char*>(ptr);
bytePtr += offset;