Reputation: 65
In writing a custom allocator, I have a situation like the MWE below where placement-new is used to construct an object of type S
at a suitably aligned position in a buffer, yielding a pointer of type "pointer to S
", which is handed out. This pointer is returned to me later, at which time I want to determine the offset of the first byte of the pointed-to object from the start of the buffer (24 in this example). My question is whether line (b) below is well-defined and if not, what the correct (UB-free) way is to compute this offset. (gcc
with -fsanitize=undefined
emits no diagnostic.)
#include <cstddef>
#include <cstdio>
#include <new>
struct alignas(8) S { int x; };
int main()
{
alignas(8) std::byte buf[80];
S* const sp{new (buf + 24) S{42}};
// ...
std::byte* const bp{reinterpret_cast<std::byte*>(sp)}; // (a)
const ptrdiff_t off{bp - buf}; // (b)
printf("%td\n", off);
}
My understanding is that after array-to-pointer decay, the expression buf
is a pointer of type "pointer to std::byte
" that points to the 0-th element of the array of element type std::byte
. It seems what [expr.add]p5 requires for line (b) to be well-defined is that bp
also be a pointer of type "pointer to std::byte
" that points to an element (or one past the end) of the same array. bp
should have the requisite type due to the reinterpret_cast
on line (a), but since S
and std::byte
are not pointer-interconvertible, the value of bp
is unchanged by the cast so would still be "pointer to *sp
", i.e. bp
aliases (points to) the object of type S
nested in the array. It is unclear to me whether bp
pointing to the object of type S
nested in the array means bp
points to an element of the array itself as well or not, for the purpose of applying [expr.add]p5.
Upvotes: 4
Views: 109
Reputation: 504
The pointer-to-integer conversion is implementation-defined, which means that your implementation must document how it works. If your implementation defines the pointer-to-integer conversion as producing the numeric value of the linear address of the object referenced by the pointer, and you know that you are on a flat architecture, then what you can do is compare integers rather than pointers. Integer comparisons are not constrained in the same way that pointer comparisons are.
Raymond Chen's blog has a lot of C++ and Win32 knowledge. Although you won’t find the answers to all your questions on his blog, if you can find the answer there, it will definitely be an easy-to-understand answer.
Upvotes: 1