2

whats the cleanest way to perform pointer arithmetic in C++? I am trying to add n bytes to an address.

int *foo;
foo = static_cast<int*> (static_cast<unsigned int>(foo) + sizeof(T))

Later you could recast and use foo differently

char* somestr = reinterpret_cast<char*>(foo)

Is this good enough? Now I understand pointer implementation dosent guarantee all pointers (char*, int*) to be implemented of the same size. So not sure if int* (should it be foo*) and using unsigned int for math is the cleanest solution. Also, it has to work on both 32 and 64 bit.

Nevermind why Im doing this. Its not all that unusual though. You would run into this issue anytime youre working with a stream (or bytepool) of data that is interpreted dynamically into different types.

excalibur
  • 924
  • 2
  • 11
  • 26
  • What you're doing here is either absolutely wrong or not very well comprehensible... I suggest you to RTM: http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/pointer.html –  Mar 08 '12 at 17:03
  • 2
    In this day and age you should find exceedingly few legitimate cases to perform pointer arithmetic. I don't know what you're trying to solve, but you likely don't need it. – David Mar 08 '12 at 17:03

2 Answers2

12

The cleanest way of doing pointer arithmetic is not via numbers of bytes, but strongly typed. Don’t treat an int array as something else, just offset directly:

int* next = foo + n;

or:

int* next = &foo[n];

Both are superior to your casting solution.

In cases where you work on byte buffer, use char*, not (never!) int*. That is,

char* buffer = get_the_buffer();

// Pointer arithmetic uses sizeof(char) == 1

If you really need to increment bytewise inside a non-byte array, first ask yourself why the hell you are doing that. Then, cast to char* and do the pointer arithmetic; do not cast to int or other integral types:

char* foo_buffer = reinterpret_cast<char*>(foo);
char* whatever = foo_buffer + n;

Instead of char you can also use unsigned char which arguably makes more sense to represent bytes but has no influence on pointer arithmetic. Be careful with alignment however: you cannot reliably access the incremented pointer using the original type any more. It is strictly undefined behaviour (= bad!) to access unaligned memory. In the best cases it’s slow. In the worst case, it crashes.

It goes without saying that all of this is extremely low level. There are almost no uses for such code any more. Even low-level libraries should prefer to use C++ standard library facilities for this kind of code, and pointer arithmetic in particular has fewer and fewer uses.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • You're first two snippets aren't quite what the question had, foo is an `int *`. Definitely use `char *` for buffer management. – Skizz Mar 08 '12 at 17:16
  • @Skizz To be honest I’m not really sure what is asked but in the question `foo` is also declared as `int*` and if we assume that the code makes sense at all then `T` must be `int`, so the code effectively does array indexing. – Konrad Rudolph Mar 08 '12 at 17:22
  • I think youre missing the point. The foo* is pointing to an arbitrary memory location (reinterpreted by application). I dont think char* is a good idea since (Im told) pointer implementation need not be uniform. So I was wondering if maybe void* is the safest choice to store foo. Appreciate the answers. – excalibur Mar 08 '12 at 17:45
  • 2
    @excalibur You were told wrong (or you misunderstood), and the statement makes no sense. `int*` for arbitrary memory locations is always wrong. `int*` means one thing, and one thing only: “pointer to a consecutive block of one or more `int`”. `void*` is also wrong here; has the sole purpose to provide type erasure. It *cannot* be used with pointer arithmetic (just try it!). **`char*` is the only right type here**, don’t be mislead by the stupid type name. In C++, `char` is an alias for the (non-existing) type `byte`. – Konrad Rudolph Mar 08 '12 at 19:24
  • You can refer to the comments for this question 399003 http://stackoverflow.com/questions/399003/is-the-sizeofsome-pointer-always-equal-to-four "There are no other guarantees, including no guarantee that sizeof(int *) == sizeof(double *)." which is why I was wondering if I should use "void ptr" for foo. Ofcourse not for arithmetic - thats where I was trying to covert to "unsigned int" – excalibur Mar 09 '12 at 14:33
  • @excalibur C++ guarantees two things: first of all, that `sizeof(char) == 1` which means that if you want to manipulate bytes, `char` is the type to go to. This is unrelated to pointers. The second guarantee (but that’s not really relevant here) is that you can map each pointer-to-object type to `char*` (and vice-versa), even if the sizes of pointers are not guaranteed to be identical. And just to mention that again, `void*` shouldn’t be used here at all. – Konrad Rudolph Mar 09 '12 at 14:42
1

You're casting from a pointer to an int, which can fail, especially if the size of the int type is different to the size of the pointer type.

If you want to do pointer arithmetic then use pointers:

foo = reinterpret_cast <int *> (reinterpret_cast <T *> (foo) + 1);

Note the use of reinterpret_cast instead of static_cast.

More importantly, this is a bit of a code smell - what are you trying to achieve here?

Skizz
  • 69,698
  • 10
  • 71
  • 108