Was macht Casting auf Compiler- / Maschinenebene?

8

Ich habe mich oft gefragt, was Casting auf Compiler- oder Maschinenebene genau macht. Was macht es mit den 0 und 1s im Speicher?

Kann mir jemand auf eine gute Literatur hinweisen?

    
uriDium 24.03.2009, 08:12
quelle

7 Antworten

6

Casting verändert nicht die einzelnen Bits beim Umsetzen zwischen Referenztypen, es weist den Compiler / Runtime nur an, die Bits nach Möglichkeit in einer bestimmten Weise zu interpretieren.

Wenn die Umwandlung zum Kompilieren aufgrund inkompatibler Typen nicht möglich ist, wird ein Fehler ausgegeben. Wenn die Umwandlung zur Laufzeit nicht möglich ist, wird eine Ausnahme ausgelöst.

Die Wiki-Seite zur Typenkonvertierung enthält zusätzliche Informationen.

    
Brian Rasmussen 24.03.2009, 08:18
quelle
2

In C für nicht numerische Typen wird beim Casting für 0 und 1s im Speicher nichts verwendet.

Bei numerischen Typen nimmt der C-Compiler eine Konvertierung vor, so dass der numerische Wert so gut wie möglich gleich bleibt.

Wenn Sie numerische Typen umwandeln möchten, ohne die Bit-Werte zu ändern, müssen Sie einen Union- oder Cast-Zeiger verwenden (der folgende Code veranschaulicht den letzteren):

%Vor%     
mouviciel 24.03.2009 08:59
quelle
2

Was Casting betrifft, wäre eine nützliche Literatur die JavaTM Virtual Machine Spezifikation .

Im Abschnitt Conversions und Werbeaktionen würden Sie dies tun Es gibt sechs große Arten von Conversions:

  • Identitätskonvertierungen
  • Grundlegende Konvertierungen erweitern
  • Primitive Conversions einschränken
  • Erweiterung der Referenzkonvertierungen
  • Einschränkende Referenzkonvertierungen
  • String-Konvertierungen

Es gibt fünf Konvertierungskontexte, in denen Konvertierungsausdrücke vorkommen können, einschließlich der Casting-Konvertierung :

  

Casting-Kontexte ermöglichen die Verwendung von:

     
  • eine Identitätskonvertierung,
  •   
  • eine erweiterte primitive Konvertierung,
  •   
  • eine verengende primitive Konvertierung,
  •   
  • eine erweiterte Referenzkonvertierung oder
  •   
  • eine einschränkende Referenzkonvertierung.
  •   

Casting-Conversions sind also umfassender als Conversions für Umsetzungs- oder Methodenaufrufe: Eine Umwandlung kann eine beliebige andere Konvertierung als eine Zeichenfolgenkonvertierung durchführen.

     

Casting kann einen Wert eines beliebigen numerischen Typs in einen anderen numerischen Typ konvertieren. Ein Wert vom Typ boolean kann nicht in einen anderen Typ umgewandelt werden. Ein Wert des Referenztyps kann nicht in einen Wert des primitiven Typs umgewandelt werden.

     

Einige Umwandlungen können zur Kompilierzeit als falsch erkannt werden und führen zu einem Fehler bei der Kompilierung. Andernfalls kann entweder der Cast zum Zeitpunkt der Kompilierung als korrekt bestätigt werden oder es ist eine Überprüfung auf Gültigkeit der Laufzeit erforderlich. (Einzelheiten finden Sie in der JavaTM-Sprachspezifikation ).
Wenn der Wert zur Laufzeit eine Nullreferenz ist, ist die Umwandlung zulässig. Wenn die Überprüfung zur Laufzeit fehlschlägt, wird eine ClassCastException ausgelöst.

    
VonC 24.03.2009 09:04
quelle
1

Angenommen, es handelt sich hier nur um eine Referenztypumsetzung und nicht um eine Konvertierung (z. B. int in Byte), glaube ich Folgendes:

1) Überprüfen Sie, ob die Referenz null ist - wenn ja, beenden Sie. 2) Folgen Sie der Referenz, um das Objekt im Speicher zu finden. In der Objektkopfzeile gibt es Informationen, die den Typ angeben. 3) Prüfen Sie anhand der Typinformation, ob der Zieltyp in der Hierarchie liegt. Wenn dies nicht der Fall ist, werfen Sie eine ClassCastException mit entsprechenden Informationen.

Die "Bits" des Ergebnisses sind immer die gleichen wie die "Bits" der Eingabe (vorausgesetzt, ist eine Ausgabe anstelle einer Ausnahme), aber dann kennt die JVM den Typ der Referenz, so dass andere Operationen garantiert erfolgreich sind.

    
Jon Skeet 24.03.2009 08:17
quelle
1

Man muss auch verstehen, wie Referenzen sowohl zur Kompilier- als auch zur Laufzeit funktionieren.

Jeder Typ enthält eine Nachschlagetabelle für jede Methode, die aufgelöst wird Jede Methode für die aufgelöste Methode dieses Typs.

Wenn Ihre Referenz ein Objekt ist, ruft toString () das Richtige auf und findet die am meisten abgeleitete Methode toString (). Casting ist erforderlich, damit die Laufzeitumgebung garantieren kann, dass jede gegebene Referenz tatsächlich über Zielmethoden für jede Methode verfügt, die in der Referenz verfügbar gemacht wird. Nach dem Übergeben der Besetzung von X nach Y kann jede Referenz vom Typ Y sichergestellt werden, dass alle ihre Methoden auf der gegossenen (sp) Referenz verfügbar sind.

    
mP. 24.03.2009 09:15
quelle
1

Andere haben die Grundlagen behandelt, aber ich möchte ein paar Worte darüber sagen, wie ein Compiler implementiert wird, der in seinem Fall aufschlussreich sein könnte.

Der Compiler verwaltet eine Liste (die Symboltabelle genannt wird) mit Variablen Namen , die an einem bestimmten Punkt im Programm verwendet werden, sowie einige Informationen über die Variablen. Die Liste der Informationen enthält:

  • ihr zugewiesener Speicher (in diesem Register, an diesem Speicherort usw.)
  • welcher Typ sie sind (d. h. Ganzzahl oder Zeichenkette oder SubWhatsitObj ) einschließlich aller Einschränkungen (wie zB der Konstanten)
  • alle Verknüpfungsinformationen, die der Compiler benötigt

Der Compiler verwendet diese Informationen, um zu entscheiden, wie Ausdrücke mit den Variablen behandelt werden sollen. Die Art von Metainformationen, die in der Symboltabelle gespeichert sind, kann auch für jeden Ausdruck von seinen Komponenten abgeleitet werden.

Außer im Sonderfall der numerischen Typumwandlung teilt eine Umwandlung dem Compiler lediglich mit, dass er andere Meta-Informationen für eine Variable oder einen Ausdruck verwenden soll, als dies normalerweise der Fall wäre. Es sind überhaupt keine Bits im Speicher betroffen, aber das Ergebnis einer Berechnung kann sein.

    
dmckee 24.03.2009 13:26
quelle
1

Es kommt darauf an, was Sie spielen. Bei numerischen Umwandlungen (float zu int und zurück) versucht die CPU, die nächste Zahl zu finden, die in das Ziel passt.

Bei Typ-Fällen wird nichts gespeichert. Es ist nur eine Möglichkeit für den Softwareentwickler, dem dummen Compiler zu sagen, dass eine Variable einmal so behandelt werden sollte, als ob sie von einem anderen Typ wäre.

Ich habe versucht, einige Informationen über Regeln für das numerische Gießen zu googeln, aber es gibt nicht viel zu tun. Sie können den C99-Standard ausprobieren, aber ich bin mir nicht sicher, ob dies der Fall ist wird dich überwältigen. IIRC, die Regeln sind:

  • Durch das Herunterdrücken (großer Typ - & gt; kleinerer Typ wie double - & gt; float - & gt; int - & gt; Byte) werden Informationen abgeschnitten, die nicht dargestellt werden können (so dass double- & gt; float verliert) Genauigkeit, - & gt; int wird alle Dezimalstellen + keine Rundung verlieren.

  • Das Auffüllen (kleinerer Typ - & gt; größerer Typ) bedeutet, die zusätzlichen Bits mit '0' zu füllen.

Natürlich gibt es Zahlen, die Sie nicht wirklich darstellen können (wie 0.1 ). Jede Operation an diesen, auch ohne Casting, wird Informationen verlieren (deshalb können 0,1 * 10! = 1,0 sein).

    
Aaron Digulla 24.03.2009 08:34
quelle