11

In this answer, int8_t* is used for (byte) pointer arithmetic:

std::size_t offset = offsetof(Thing, b);
Thing* thing = reinterpret_cast<Thing*>(reinterpret_cast<int8_t*>(ptr) - offset);

I've always used char* in the past but the comments are really confusing, and nobody responded, so I posted this separate question.

Is char* valid, and the preferred way of doing these calculations?

Community
  • 1
  • 1
Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176

1 Answers1

2

You must use char*: the behaviour on using a reinterpret_cast with int8_t* on a pointer to something that is not an int8_t is undefined. Casting to char* can be viewed as an exception to the rule.

Pre C++14, char can be a 1's complement type with range -127 to +127. int8_t must be 2's complement. Even C++14 and onwards, I can't see why the types are related: char can still be either a signed or an unsigned type.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • Regarding the pointer sizes, I thought all pointers to objects had the same size in C++. Is this not guaranteed? But whatever the answer, pointer arithmetic is affected by `sizeof(T)`, not `sizeof(T*)`. At any rate, the point about aliasing stands. – Konrad Rudolph Nov 23 '15 at 13:56
  • Your last point is correct: the sizeof(*) is not relevant so I've removed it as it only weakens the answer. As for your first point, I can't see why pointers to objects are relevant. We only have PODs here. – Bathsheba Nov 23 '15 at 13:59
  • 1
    None of the first paragraph is true. `uint8_t` is indeed not part of the special permission in the strict aliasing rule, but the pointer isn't being used for type punning here, only for pointer arithmetic. The rules for pointer arithmetic are rather more permissive, and require only that the alignment is appropriate and the arithmetic doesn't take you outside the same complete object.... and there are no special permissions for `char*` there. – Ben Voigt Nov 23 '15 at 14:07
  • I disagree. You could end up assigning a pointer to memory you don't own, which, aside from one-past-the-array, is undefined behaviour. (And dereferencing `thing` will not end well.). Are you in a position to answer the question? – Bathsheba Nov 23 '15 at 14:13
  • @Bathsheba “object” in C++ parlance means “memory location”. *Every* value is an object, and an object pointer distinguishes it from function pointer (and maybe `void*`). – Konrad Rudolph Nov 23 '15 at 14:59
  • Does anybody willing to write a proper answer? – Karoly Horvath Nov 24 '15 at 10:30