Ich bin auf der Suche nach einer Funktion, die bestimmt, ob ein bestimmter Zeiger auf einen bestimmten Puffer zeigt. Die Spezifikation:Wie kann ich sicher und sinnvoll feststellen, ob ein Zeiger irgendwo in einen bestimmten Puffer zeigt?
template <typename T>
bool points_into_buffer (T *p, T *buf, std::size_t len);
Wenn es etwas n
ist, 0 <= n && n < len
, für die p == buf + n
, kehrt true
.
Andernfalls, wenn es einige n
, 0 <= n && n < len * sizeof(T)
gibt, für die reinterpret_cast<char *>(p) == reinterpret_cast<char *>(buf) + n
, ist das Verhalten nicht definiert.
Andernfalls gibt false
zurück.
Die offensichtliche Umsetzung etwas wie
template <typename T>
bool points_into_buffer (T *p, T *buf, std::size_t len) {
return p >= buf && p < buf + len;
}
aussehen würde, aber das hat Verhalten in Standard C++ undefined: relationale Vergleiche von Zeigern sind nur für den Zeiger in das gleiche Array definiert.
Eine Alternative wäre die Standard-Bibliothek Vergleich Objekte zu verwenden:
template <typename T>
bool points_into_buffer (T *p, T *buf, std::size_t len) {
return std::greater_equal<T *>()(p, buf) && std::less<T *>()(p, buf + len);
}
die true
zurückzukehren garantiert, wenn ich es true
zurückkehren will, und nicht definiertes Verhalten vermeidet, aber für Fehlalarme erlaubt: gegeben int a; int b;
Es ermöglicht ein Ergebnis von true
für points_into_buffer(&a, &b, 1)
.
Es kann als eine Schleife realisiert werden:
template <typename T>
bool points_into_buffer (T *p, T *buf, std::size_t len) {
for (std::size_t i = 0; i != len; i++)
if (p == buf + i)
return true;
return false;
}
jedoch Compiler Schwierigkeiten haben, zu optimieren, dass die Schleife weg.
Gibt es eine gültige Möglichkeit, dies zu schreiben, wenn bei aktuellen Compilern und Optimierungen das Ergebnis in konstanter Zeit ermittelt wird?
Woran denken Sie, dass die Verwendung von Vergleichsfunktionen nicht zu undefiniertem Verhalten führt? Sie sind so definiert, dass sie die einfachen relationalen Operatoren verwenden, daher sollte hier kein Unterschied bestehen. – Horstling
@Horstling C++ 11 [Vergleiche] p8 "Für die Vorlagen' größer', 'weniger',' größer_gleich' und 'weniger_gleich' ergeben die Spezialisierungen für jeden Zeigertyp eine Gesamtordnung, selbst wenn die eingebauten Operatoren' <', '> ',' <=', '> = 'nicht." – hvd
@hvd Interessant (und ein wenig kontraintuitiv). Wusste das nicht, thx. – Horstling