Soll ich static_cast oder reinterpret_cast verwenden, wenn ich eine void* in was auch immer umwandele

Lesezeit: 6 Minuten

Soll ich static cast oder reinterpret cast verwenden wenn ich eine void
Andy

Beide static_cast und reinterpret_cast scheinen für das Casting gut zu funktionieren void* zu einem anderen Zeigertyp. Gibt es einen guten Grund, das eine dem anderen vorzuziehen?

  • @anon Anscheinend hast du vorher noch nie mit POSIX-Threads gearbeitet.

    – Benutzer470379

    23. Dezember 2010 um 20:00 Uhr

  • @ user470379 Wow … das ist genau der Grund, warum ich bei SO auf diese Frage gelandet bin! Hervorragende Beobachtung :-).

    – Oger Psalm33

    21. Juni 2011 um 14:13 Uhr

Soll ich static cast oder reinterpret cast verwenden wenn ich eine void
Konrad Rudolf

Verwenden static_cast: es ist der engste Guss, der genau beschreibt, was hier umgebaut wird.

Es gibt ein Missverständnis, dass mit reinterpret_cast wäre eine bessere Übereinstimmung, weil es bedeutet, „Type Safety komplett zu ignorieren und einfach von A nach B zu casten“.

Dies beschreibt jedoch nicht wirklich die Wirkung von a reinterpret_cast. Eher, reinterpret_cast hat eine Reihe von Bedeutungen, für die alle gilt, dass „die Abbildung durchgeführt von reinterpret_cast ist implementierungsdefiniert.“ [5.2.10.3]

Aber im speziellen Fall des Gießens ab void* zu T* das Mapping ist durch den Standard vollkommen wohldefiniert; nämlich einem typlosen Zeiger einen Typ zuzuweisen, ohne seine Adresse zu ändern.

Dies ist ein Grund zu bevorzugen static_cast.

Zusätzlich und wohl noch wichtiger ist die Tatsache, dass jede Verwendung von reinterpret_cast ist geradezu gefährlich, weil es wirklich alles in etwas anderes umwandelt (für Zeiger), während static_cast ist viel restriktiver und bietet somit ein besseres Schutzniveau. Dies hat mich bereits vor Fehlern bewahrt, bei denen ich versehentlich versucht habe, einen Zeigertyp in einen anderen zu zwingen.

Die static_cast eignet sich besser zum Konvertieren von a void* zu einem Zeiger eines anderen Typs.

static_cast ist die Besetzung der Wahl, wenn es eine natürliche, intuitive Konvertierung zwischen zwei Typen gibt, die nicht unbedingt zur Laufzeit funktioniert. Sie können zum Beispiel verwenden static_cast Basisklassenzeiger in abgeleitete Klassenzeiger zu konvertieren, was in manchen Fällen sinnvoll ist, aber erst zur Laufzeit verifiziert werden kann. Ebenso können Sie verwenden static_cast umwandeln von einem int zu einem chardie gut definiert ist, aber bei der Ausführung zu einem Genauigkeitsverlust führen kann.

reinterpret_cast, auf der anderen Seite, ist ein Casting-Operator, der für Konvertierungen entwickelt wurde, die grundsätzlich nicht sicher oder nicht portabel sind. Sie können zum Beispiel verwenden reinterpret_cast umwandeln von a void * zu einem intdas korrekt funktioniert, wenn Ihr System zufällig eine hat sizeof (void*)sizeof (int). Sie können auch verwenden reinterpret_cast umwandeln a float* zu einem int* oder umgekehrt, was plattformspezifisch ist, da die jeweiligen Darstellungen von floats und ints haben nicht garantiert etwas miteinander gemeinsam.

Kurz gesagt, wenn Sie jemals eine Konvertierung durchführen, bei der die Umwandlung logisch sinnvoll ist, aber zur Laufzeit möglicherweise nicht unbedingt erfolgreich ist, vermeiden Sie dies reinterpret_cast. static_cast ist eine gute Wahl, wenn Sie etwas Vorwissen darüber haben, dass die Umwandlung zur Laufzeit funktionieren wird, und dem Compiler mitteilen: “Ich weiß, dass dies möglicherweise nicht funktioniert, aber es macht zumindest Sinn und ich habe Grund zu der Annahme, dass es richtig funktioniert zur Laufzeit das Richtige tun.” Der Compiler kann dann überprüfen, ob die Umwandlung zwischen verwandten Typen erfolgt, und einen Kompilierzeitfehler melden, wenn dies nicht der Fall ist. Verwenden reinterpret_cast Um dies mit Zeigerkonvertierungen zu tun, wird die Sicherheitsüberprüfung zur Kompilierzeit vollständig umgangen.

Es gibt einige Situationen, in denen Sie möglicherweise a verwenden möchten dynamic_cast anstelle einer static_castaber diese beinhalten meistens Besetzungen in einer Klassenhierarchie und betreffen (nur selten) direkt void*.

Welches von der Spezifikation bevorzugt wird, wird nicht übermäßig als “das Richtige” erwähnt (oder zumindest erinnere ich mich nicht, dass einer von ihnen so erwähnt wurde). Ich denke jedoch, dass die Spezifikation es möchte verwenden static_cast über reinterpret_cast. Wenn Sie beispielsweise eine Umwandlung im C-Stil verwenden, wie in

A* ptr = (A*) myVoidPointer;

Die erprobte Reihenfolge der Casting-Operatoren versucht immer, a zu verwenden static_cast vor einem reinterpret_castwas das gewünschte Verhalten ist reinterpret_cast ist nicht garantiert tragbar.

  • Zur Verdeutlichung: was der Autor hier mit „static_cast… funktioniert nicht unbedingt zur Laufzeit” ist: “Ihr Programm kann später abstürzen.” Wenn Sie static_cast von einem Basistyp zu einem abgeleiteten Typ, it Wille zur Laufzeit “arbeiten” (dh Sie werden nicht eine Ausnahme bekommen oder a NULL Zeiger), aber das Ergebnis kann auf den falschen Speicherort zeigen, wenn Mehrfachvererbung beteiligt ist. (Siehe diese Antwort für weitere Details.) Nur dynamic_cast führt eine Laufzeitprüfung durch (unter Verwendung von RTTI) und schlägt ordnungsgemäß fehl, wenn die Umwandlung ungültig ist.

    – andrewtc

    9. August 2014 um 22:51 Uhr


Das ist eine schwierige Frage. Auf der einen Seite macht Konrad einen hervorragenden Punkt in Bezug auf die Spezifikationsdefinition für reinterpret_cast, obwohl es in der Praxis wahrscheinlich dasselbe tut. Auf der anderen Seite, wenn Sie zwischen Zeigertypen umwandeln (wie es zum Beispiel bei der Indizierung im Speicher über ein char * ziemlich üblich ist), static_cast wird einen Compiler-Fehler generieren und Sie werden zur Verwendung gezwungen reinterpret_cast ohnehin.

In der Praxis benutze ich reinterpret_cast weil es die Absicht des Cast-Vorgangs besser beschreibt. Sie könnten sicherlich für einen anderen Operator plädieren, um nur Zeiger neu zu interpretieren (was garantiert, dass dieselbe Adresse zurückgegeben wird), aber es gibt keinen im Standard.

  • anderer Operator, um nur den Zeiger neu zu interpretieren (was garantiert, dass dieselbe Adresse zurückgegeben wird)“Umarmung? Dieser Operator ist reinterpret_cast!

    – Neugieriger

    19. Dezember 2011 um 6:18 Uhr

  • @curiousguy Nicht wahr nach dem Standard. reinterpret_cast garantiert NICHT, dass dieselbe Adresse verwendet wird. Nur das, wenn Sie_cast von einem Typ in einen anderen uminterpretieren und dann wieder zurückerhalten Sie dieselbe Adresse zurück, mit der Sie begonnen haben.

    – ClydeTheGhost

    1. März 2019 um 20:58 Uhr

Das hast du wahrscheinlich bekommen void* mit impliziter Konvertierung, also sollten Sie verwenden static_cast weil es der impliziten Konvertierung am nächsten kommt.

Verwenden static_cast dafür. Nur in den seltensten Fällen, wenn keine andere Möglichkeit besteht reinterpret_cast.

1646955012 114 Soll ich static cast oder reinterpret cast verwenden wenn ich eine void
anton_rh

Casting hin und her void* verwenden static_cast und verwenden reinterpret_cast ist identisch. Siehe die Antwort unter dem Link. Aber normalerweise static_cast wird bevorzugt, weil es eine engere und im Allgemeinen (aber nicht in diesem speziellen Fall) sicherere Konvertierung ist.

1646955013 278 Soll ich static cast oder reinterpret cast verwenden wenn ich eine void
Tim Diekmann

Ich schlage vor, immer die schwächstmögliche Besetzung zu verwenden.

reinterpret_cast kann verwendet werden, um einen Zeiger auf a umzuwandeln float. Je strukturbrechender der Gips ist, desto mehr Aufmerksamkeit erfordert seine Anwendung.

Im Falle von char*würde ich C-Style-Cast verwenden, bis wir welche haben reinterpret_pointer_castweil es schwächer ist und nichts anderes ausreicht.

  • reinterpret_cast kann verwendet werden, um einen Zeiger auf einen Float umzuwandeln.” Sicherlich nicht!

    – Neugieriger

    19. Dezember 2011 um 6:16 Uhr

  • Wahrscheinlich float f = *reinterpret_cast<const float*>(&p);

    – Ben Voigt

    7. August 2013 um 15:33 Uhr

  • @BenVoigt Das ist Casting zwischen Zeigern; Einer von ihnen war zufällig ein Float-Zeiger.

    – nodakai

    1. Juni 2016 um 15:46 Uhr

  • @BenVoigt der “gesamte Ausdruck” ist jedoch keine Besetzung. Der Ausdruck besteht aus einer Dereferenzierung, die auf eine Umwandlung angewendet wird. Sie haben behauptet, dass es möglich sei, einen Zeiger darauf zu werfen float, was falsch ist. Der Ausdruck wird umgewandelt void ** zu const float *und verwendet dann eine Dereferenzierungsoperation (die KEINE Umwandlung ist), um zu konvertieren const float * zu float.

    – MM

    27. Juli 2018 um 4:37 Uhr


  • @BenVoigt Sie haben diesen Code als Antwort auf die Frage von jemandem angeboten: “Wie wirke ich …”, und als dann jemand sagte, dass der Code zwischen Zeigern wirft (was er tut), sagten Sie “Nein”.

    – MM

    27. Juli 2018 um 4:54 Uhr

989270cookie-checkSoll ich static_cast oder reinterpret_cast verwenden, wenn ich eine void* in was auch immer umwandele

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy