Was soll Casting bedeuten?

18

Wenn Sie in einfachen Sprachen wie CI codieren, bedeutet Casting manchmal "interpretieren Sie diese Bytes neu, als ob es immer von einem anderen Typ gewesen wäre" und zu anderen Zeiten "konvertieren Sie diesen Wert intelligent in diesen anderen Typ".

Was ist die ursprüngliche Bedeutung des Wortes und gibt es eine Übereinstimmung, wann mit einer Konvertierung und wann mit einer rohen Neuinterpretation zu rechnen ist?

Alexander Torstling
quelle
Was verstehen Sie in einem Wikipedia-Artikel nicht? „ Typumwandlung , eine Schublade gesteckt und Zwang gibt verschiedene Möglichkeiten, implizit oder explizit, eine Einheit von einem Datentyp in einen anderen zu ändern ... Jede Programmiersprache hat ihre eigenen Regeln auf , wie Typen umgewandelt werden kann ...“
gnat
Die ursprüngliche Bedeutung von "Besetzung" hat nichts mit der Programmierung zu tun, siehe hier merriam-webster.com/dictionary/cast
Doc Brown
1
Viele (meistens aus der Perspektive einer verwalteten Sprache) auf Eric Lipperts Blog in der Kategorie der Darsteller
AakashM
1
@gnat: Ich bin mir nicht sicher, ob das eine ernsthafte Frage oder nur ein Trolling-Versuch ist. Aber ich möchte wissen, wie ich weiß, was der Compiler tun wird: konvertieren, gießen oder erzwingen? Was sind die Faustregeln?
Alexander Torstling
1
@DocBrown Ich denke, der Begriff castim Computerbereich ähnelt eher dem Begriff Gießen im metallurgischen Bereich, bei dem sich die Form einer Metallschmelze beim Eingießen in eine Form ändert
KChaloux

Antworten:

10

Casting in C ist einzigartig, im Gegensatz zu anderen Sprachen. Es ist auch niemals intelligent.

Das Casting in C konvertiert Werte von einem Typ in einen anderen unter Verwendung sorgfältig definierter Regeln. Wenn Sie es wirklich wissen müssen, lesen Sie die Norm. Ansonsten sind die wichtigsten Punkte:

  1. Bei der Konvertierung zwischen Ganzzahltypen bleibt der Wert nach Möglichkeit erhalten. Wenn das Ziel mehr Bits hat, ist dies verbreitert und im Allgemeinen sicher, kann aber eine Zeichenerweiterung beinhalten. Wenn enger, gehen Bits verloren.
  2. Bei der Konvertierung zwischen Zeigertypen bleibt der Zeigerwert erhalten, die Ergebnisse sind jedoch häufig undefiniert, häufig nicht portierbar und häufig für erweiterte Szenarien nützlich.
  3. Die Konvertierung zwischen Ganzzahlentypen und Zeigern ist in Ordnung, wenn die Ganzzahl groß genug ist und das Bitmuster beibehalten wird (was auch immer dies bedeuten mag). Wenn die Ganzzahl zu klein ist, ist das Ergebnis undefiniert, aber nicht nützlich. In der Regel ist 'long' breit genug für 'void *', aber keine Garantie! Zeiger, die auf diese Weise erstellt wurden, können auf alle möglichen interessanten Arten ungültig sein.
  4. Die Konvertierung zwischen Float- und Integer-Typen sind arithmetische Konvertierungen, wie sie von einer geeigneten Bibliotheksroutine definiert wurden (mit Kürzung, nicht Rundung).
  5. Sie können den Rückgabewert einer Funktion auf ungültig setzen. Ich habe nie. Es macht nichts.

Einige Casts werden implizit angewendet, und in einigen Fällen gibt der Compiler eine Warnung aus. Am besten die Warnungen beachten!

Die Wörterbuchdefinition für cast wird am besten ignoriert, da sie nicht hilfreich ist. Viele Casts lassen sich besser mit den Begriffen Bekehrung oder Zwang beschreiben, daher lohnt es sich, auch diese zu kennen.

C ++ ist VIEL komplizierter, aber das haben Sie nicht gefragt, oder?

david.pfx
quelle
Ich interessiere mich für Faustregeln und nicht für winzige Details, aber ich interessiere mich für andere Sprachen als C, wenn dies zur Aufklärung beiträgt.
Alexander Torstling
2
Was ich hier angegeben habe, ist so allgemein wie vernünftig. Um echten, professionellen C / C ++ - Code auf niedriger Ebene zu schreiben, ist das kleinste Detail entscheidend. Die meisten Sprachen haben bei der Typkonvertierung keine derartigen Probleme. Entschuldigung, wenn es Ihr Problem nicht löst.
david.pfx
Abgesehen davon, dass das Konvertieren von T*nach void*und zurück immer genau definiert ist.
Miles Rout
@Miles: Tatsächlich muss T * in ein beliebiges U * und zurück konvertiert werden, um den ursprünglichen Zeigerwert beizubehalten. In meiner Antwort habe ich nur "oft undefiniert" gesagt, um es kurz zu machen, da einige Details sehr unübersichtlich sind.
david.pfx
1
@supercat: Siehe n1570 S6.3.2.3. Beim Konvertieren / Auslösen zwischen T *, U * und void * bleibt der Zeigerwert mit nur einer Ausnahme immer erhalten. Wenn ein T * nicht korrekt ausgerichtet ist, liegt ein undefiniertes Verhalten vor. Ich akzeptiere Ihren Standpunkt, aber nur insoweit.
david.pfx
2

Dieser Teil des Webster-Wörterbuchs enthält die richtige Definition:

a: (einem Stoff) eine Form geben, indem er in flüssiger oder plastischer Form in eine Form gegossen wird und ohne Druck aushärten lässt.
b: durch diesen Prozess formen

Vor dem Casting hat Ihr "Objekt" (nicht wörtlich ein OOP-Objekt) eine bestimmte Form (Typ). Wenn Sie es neu gießen, bedeutet dies, dass Sie es mit Beton umgießen, um eine neue Form zu erhalten. Sie haben eine Zahl als hexagonale Ganzzahl und nach dem Wirken erhalten Sie eine rechteckige Zeichenfolge.

Juha Untinen
quelle
2
Außerdem : "(einem Schauspieler) eine bestimmte Rolle zuweisen".
Kelly Thomas
Jep. Ich bin sicher, das ist das Beste. +1.
david.pfx
2

Es kann nützlich sein, C-Casts in zwei Gruppen zu unterteilen:

  1. Numerische Casts - Konvertieren Sie eine Zahl zwischen Darstellungen und versuchen Sie, den Wert beizubehalten. Zum Beispiel - (int)3.1wäre 3. Es gibt genaue Regeln, die definieren, was passiert, wenn der genaue Wert nicht eingehalten werden kann.

  2. Zeigerumwandlungen - Behalten Sie die Speicheradresse bei, ändern Sie jedoch die Art und Weise, in der sie dereferenziert wird. Zum Beispiel wird für float x=3.5, *(int *)&xgeben 1080033280- diese Ganzzahl wird durch dasselbe Bitmuster dargestellt, das den Gleitkommawert darstellt 3.5.

ugoren
quelle
Keep the memory address, but change the way it's dereferenced.Die Dereferenzierung eines typgesteuerten Zeigers ist nicht definiert. Die Norm nur garantiert Gießen aus A *zu B *und Rückseite das gleiche produzieren A *, die gültig sind möglicherweise nicht in dem 1. Platz zu dereferenzieren gewesen - oder dass , wenn B *eine ist char *, kann es verwendet werden , um die Objektdarstellung von jeder Art zu lesen. Bei allen anderen Typen ist der Dereferenzierungszeiger ein B *Typ-Punning-Zeiger (UB) und verstößt gegen striktes Aliasing. Wie auch immer, selbst wenn der Compiler das obige Beispiel 2 aus diesem Grund nicht verworfen hat, machen Sie unportable Annahmen über Bitmuster
underscore_d
1
cast (v): to receive form in a mold

In C ++ können die verschiedenen Arten von Umwandlungen expliziter gestaltet werden, mit der reinterpret_castBedeutung "Behandle diese Bytes so, als wären sie bereits diese andere Sache". In C können Sie dies durch die Verwendung von a absolut explizit machen. Durch das unionCasting mit dem (type)Operator wird versucht, das Ergebnis numerisch äquivalent zu halten, bis es an Präzision verliert.

U2EF1
quelle
2
In C werden Zeigermodelle immer neu interpretiert und Wertmodelle erhalten den Wert immer so gut wie möglich. In C ++ gibt es mehrere Möglichkeiten, eine Zeigerumwandlung durchzuführen, weshalb es die expliziteren Umwandlungstypen gibt.
Jan Hudec
C-Zeiger-Cast-Semantik muss nicht unbedingt "neu interpretiert" werden. Es wäre legitim, wenn ein Prozessor, der eine Wortadressierung verwendet, aber eine gute Interaktion mit bytebasiertem Code wünscht, int*ein Wort und ein Wort mit char*zwei Wörtern hat (wobei das zweite Byte das hohe oder niedrige Byte eines Wortes auswählt). Das Umsetzen eines (int*)to (char*)würde das Hinzufügen eines zusätzlichen Wortes erfordern, das den Wert haben sollte, der das erste Byte des int.
Supercat