Beim Schreiben eines benutzerdefinierten Allocators habe ich eine Situation wie die MWE unten, in der die Platzierung innehiert, um ein Objekt vom Typ S an einer angemessen ausgerichteten Position in einem Puffer zu erstellen und einen Zeiger vom Typ "Zeiger auf S " zu ergeben, der ausgehändigt wird. Dieser Zeiger wird mir später zurückgegeben. Zu diesem Zeitpunkt möchte ich den Versatz des ersten Bytes des Point-to-Objekts vom Beginn des Puffers (24 in diesem Beispiel) bestimmen. Meine Frage ist, ob Zeile (b) unten gut definiert ist und wenn nicht, was die richtige (UB-freie) Art ist, diesen Offset zu berechnen. (
mit -fSanitize = undefined emitiert keine Diagnose.)
Code: Select all
#include
#include
#include
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(sp)}; // (a)
const ptrdiff_t off{bp - buf}; // (b)
printf("%td\n", off);
}
Mein Verständnis ist, dass der Ausdruck BUF nach dem Array-zu-Punkt-Zerfall ein Zeiger vom Typ "Zeiger auf std :: byte " ist, der auf das 0-te-Element des Array von Elementtyps Std :: byte zeigt. Es scheint, dass [expr.add] p5 für Zeile (b) gut definiert ist, dass BP auch ein Zeiger vom Typ "Zeiger auf std :: byte " ist, der auf ein Element (oder eins über das Ende) desselben Arrays hinweist. BP sollte den erforderlichen Typ aufgrund der neu interpret_cast in Zeile (a) haben, aber da s und std :: byte nicht zeigerinterkonvertierbar sind, ist der Wert von bp unverändert durch den Guss. im Array. Mir ist unklar, ob BP auf das Objekt vom Typ S , das im Array verschachtelt ist>