Delphi-PRAXiS
Seite 2 von 4     12 34      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Typecast or not? (https://www.delphipraxis.net/127181-typecast-not.html)

jfheins 8. Jan 2009 22:07

Re: Zufallszahl generieren
 
Um auch mal meinen Senf dazuzugeben:

Das ganz oben (auf dieser Seite) sind für mich keine impliziten Typecasts.

Explizit ist sowas wie var := PChar(string);

Implizit etwas wie double := floatvar; es wird konvertiert, aber man muss es nicht sagen

und inttostr sind nützliche Hilfsfunktionen, die einem einen integer in eine lesbare Form wandeln.
(in .net vll. besser gelöst, da bringt jede Zahl ihre toString() Methode gleich mit ^^)




Zitat:

Zitat von WInfo
Hier werden zwei implizite Casts gemacht (i = integer und s = string) wobei diese jedoch den selben Typ besitzen und daher keine Konvertierungen vorgenommen werden. Bei der Zuweisung i = integer, gilt das oben gesagt, ebenfalls kein expliziter Cast.

Erst ein Cast aber dann doch keine Konvertierung? Für ich beinhaltet ein Cast immer ein Konvertierung :gruebel:

Namenloser 8. Jan 2009 22:32

Re: Zufallszahl generieren
 
Zitat:

Zitat von WInfo
und was möchtest Du damit sagen? :gruebel:

Ein Integer wird einem Float zugewiesen. Dabei wandelt der Compiler den Integer implizit in ein Float um.

Inttostr ist für mich kein Typecast, sondern eine Funktion. Nach deiner Defintion wäre ja jede Funktion, deren Rückgabewert von einem anderen Typ ist als der oder die Eingabeparameter, ein Typecast.
Dannw wäre also auch sowas nach deiner Definition ein Typecast:
Delphi-Quellcode:
function IsNegative(Value: integer): Boolean;
begin
  result := Value > 1;
end;

...
if IsNegative(3) then ... // <-- Typecast? IMO nicht
[edit]Wäre nett, wenn jemand das Thema splitten könnte[/edit]

Meflin 8. Jan 2009 22:36

Re: Zufallszahl generieren
 
Zitat:

Zitat von NamenLozer
Dannw wäre also auch sowas nach deiner Definition ein Typecast:

Das ist ein Argument. Dann sollte man meine obige Aussage noch so erweitern: Der dargestellte Wert bleibt dabei der gleiche (nicht aber seine Repräsentation!).

mkinzler 8. Jan 2009 22:54

Re: Typecast or not?
 
Ich habe diesen Thread von hier abgetrennt. Da die Diskussion nichts mehr mit der ursprünglichen Frage zu tun hatte.

Muetze1 8. Jan 2009 23:31

Re: Zufallszahl generieren
 
Moin!

Zitat:

Zitat von jfheins
Für ich beinhaltet ein Cast immer ein Konvertierung :gruebel:

Ein Cast ist die Anweisung für den Compiler etwas entgegen seines bekannten Typs anders zu interpretieren. Der Compiler weiss, es ist ein Integer, aber du kannst ihm sagen, nein, betrachte es als double oder string. Dabei wird nur die Betrachtungsweise der Daten im Speicher an der Stelle geändert. Es findet jedoch keine Wandlung der Daten in irgendeiner Form statt.

Ein Konvertierung wandelt vorhandene Daten und erzeugt neue. Diese können zwar wieder auf die Originale Speicherstelle abgelegt werden, aber die zugrunde liegenden Daten dienen als Ausgangspunkt für eine explizite Arbeitsanweisung.

//EDIT: Einschub Anfang - Beispiel in elektronischer Form -
Ein Integer liegt im Speicher in seiner binären Form vor, also eine Basis von 2 und das linear hintereinander. Um diesen mit der Basis von 10 auszugeben, muss er konvertiert werden und ist mit einer Basis von 10 nicht mehr binär als Integer im System speicherbar, da dieses fest mit der Basis von 2 arbeitet. Somit muss zwangsweise ein Typ her, der die Daten mit der Basis von 10 aufnehmen kann, also ein String. Gleiches gilt für die BCD Kodierung, welche zwar auch die Basis von 2 nutzt, aber eine anderen Einteilung hat. Hintergrund ist hierbei, dass pro Stelle 6 mögliche Werte ungenutzt bleiben (1 Nibble pro Dezimalstelle = 4 Bit = 2^4 = 16 Kodierungsmöglichkeiten von denen nur 0..9, also 10 Möglichkeiten genutzt werden). Die hexadezimale Schreibweise nutzt das volle Nibble zur Darstellung.

Ok, damit haben wir 4 Bits, also 4 digitale Steuerleitungen die 0 & 1 sein können. Wenn ich diese nun ausgeben will, dann kann ich 4 Leuchtdioden nehmen und man kann den Wert ablesen. Hier ist kein Typecast nötig, alles 1:1 verdrahtet. Pro Bit eine LED - passt.

Wenn ich nun aber eine 7 Segmentanzeige habe, dann habe ich nun die Möglichkeit für einen Typecast und einer Konvertierung, da ich 4 Ausgänge habe aber 7 Eingänge an der Anzeige. Eine Konvertierung wäre ein 4-zu-7 Dekoder. Dieser hat einen Eingang von 4 Signalen und 7 Ausgangssignale und der konvertiert die Signale entsprechend. Alles angeschlossen und die Anzeige zeigt die BCD Wert an. Abhängig vom 4-zu-7 Dekoder kann sie auch die hexadezimale Darstellung.
Und nun zum Typecast: ein Typecast wäre hier nun die 4 Leitungen an 4 Segmente der Segmentanzeige zu legen. Die 3 noch nicht beschalteten Eingänge kann man nun freilassen oder man schaltet welche zusammen. Dies wäre ein Typecast, weil man sagt, er soll die 4 Leitungen als 7 Leitungen betrachten. Die Anzeige wird dann schöne Symbole anzeigen, aber selten was was verständliches. Abhängig von der Beschaltung kann das geübte Auge wieder die 4 Ausgänge den LEDs der Segmente zuordnen und man wäre wieder beim ersten Beispiel mit der 1:1 Beschaltung auf 4 LEDs.
//EDIT: Einschub Ende

Alles was in Delphi mit Compilermagic gemacht wird, ist meistens eine Konvertierung. Die Compilermagic selbst fügt diese Konvertierung hinzu. Wäre keine Konvertierung nötig, wäre auch kein Compilermagic nötig.

Ein Beispiel für eine strukturierten Cast wäre eine Union, welche u.a. in Delphi auch genau für einen Typecast eingesetzt wird.

Delphi-Quellcode:
var
  lHighDWord, lLowDWord: LongWord;
  lInt64: Int64;
begin
  lInt64 := $1234567890abcdef;

  lHighDWord := Int64Rec(lInt64).Hi;
  lLowDWord := Int64Rec(lInt64).Lo;
end;
Der Int64Rec beinhaltet eine Definition um ein und die selbe Speicherstelle in einer Größe von 8 Byte unterschiedlich zu betrachten. Einmal in Form von 2 DWords und einmal in Form von einem Int64. Die Daten im Speicher werden nicht konvertiert, es werden keine neuen Daten erzeugt. Die Zugriffe auf Int64Rec.Hi bzw. Int64Rec.Lo sind Zugriffe direkt auf die Bytestellen des lInt64. Die Union definiert nur eine Menschenlesbare Form bzw. Definition von Byte Offsets.

Ein anderer Fall mit Compilermagic:
Delphi-Quellcode:
var
  lDouble: double;
  lInt: integer;
begin
  lInt := 4556;
  lDouble := lInt;
end;
Hier wird intern eine Konvertierung durchgeführt: der Compiler erweitert eine Ganzzahl um den fraktionalen Teil und macht ihn zu einer Fliesskommazahl. Der Wert an sich wird (eigentlich) nicht verändert, aber es ist eine Konvertierung, da aus den alten Daten (lInt) neue Daten (lDouble) generiert werden.

Ein anderer Fall, harter Typecast, keine Compilermagic:
Delphi-Quellcode:
var
  lHigherObject: TStrings;
  lBaseObject: TObject;
begin
  lBaseObject := TObject.Create;

  lHigherObject := TStrings(lBaseObject);
end;
Ohne den typecast wird der Delphicompiler korrekterweise meckern, da die Typen unterschiedlich und nicht zuweisungskompatibel sind. Der type-cast wiederrum macht keine Konvertierung - aus der TObject Instanz wird keine TStrings Instanz. Hier sagt man dem Compiler nur: ich weiss, das ist ein TObject, aber ich sage dir: betrachte es als TStrings Typ. Da TStrings zu TStrings typengleich sind, hat der Compiler nichts dagegen. Er macht es, aber es wird nichts konvertiert bzw. überprüft.

Der ordentliche Weg wäre hier eine Überprüfung der Typen, aber das ist in diesem Beispiel mal keine Compilermagic sondern versteckt sich in einem Operator (bzw. zwei, da AS IS beinhaltet).

Das bei dem Beispiel nichts konvertiert wurde ist einfach zu sehen beim Zugriff auf die von TStrings eingeführten Methoden und Eigenschaften.

Ein oft genutzter typecast ist auch die Vorzeichenbehaftung zu entfernen. Beispiel:
Delphi-Quellcode:
var
  lSigned: LongInt;
  lUnsigned: LongWord;
begin
  lSigned := -1;
  lUnsigned := $ffffffff;

  if lSigned = lUnsigned then
    ;
end;
Der Compiler warnt hier, dass er extra Code eingeführt hat, da der Vergleich so nicht gut durchführbar ist. Er warnt über den Vergleich von signed und unsigned Werten. Er sagt auch, dass er beide Werte erweitert hat. Der Programmierer will hier die Zahlenwerte vergleichen und Delphi erkennt das Dilemma, denn lUnsigned kann Werte bis 4,2 Milliarden annehmen, aber dafür keine unter 0 und lSigned nur bis 2,1 Milliarden, aber das mit und ohne Vorzeichen. Delphi kann nun aber schlecht den lSigned zu einem unsigned machen um es zu vergleichen, weil dann würden alle negativen Zahlen wegfallen. Auch kann er den lUnsigned nicht zu einem signed machen, dann würden alle Werte über 2,1 Milliarden wegfallen. Also erweitert er beide auf den nächst grösseren Typ und vergleicht denn. Um die Warnung wegzubekommen greifen viele Programmierer aber schnell mal zu typecast:

Delphi-Quellcode:
var
  lSigned: LongInt;
  lUnsigned: LongWord;
begin
  lSigned := -1;
  lUnsigned := $ffffffff;

  if LongWord(lSigned) = lUnsigned then
    ;
end;
Und dabei tritt dann genau das oben genannte Problem auf: Die negativen Zahlen falle weg. In diesem Falle wäre hier sogar von Gleichheit auszugehen, da die binäre Form von -1 eines signed 32 Bit Wertes so aussieht, dass das MSB gesetzt ist (Bit 31) (Vorzeichen Bit) und alle anderen Bits negiert sind. Somit wäre es bei -1 genau $ffffffff. Somit würde ein Vergleich der oben nach der Korrektur von Delphi mit der Erweiterung noch fehlschlägt bei einem Typecast richtig sein. Hier sieht man vor allem, dass Delphi hier keine Konvertierung der Daten vornimmt sondern einfach den Speicherinhalt neu interpretiert bzw. betrachtet mit der aufgezwungenen Brille eines unsigned dwords.

Und zu den Dingen bezüglich harter und weicher Cast, so wäre dies am besten auch in C++ erklärbar (dynamic_cast<>() && static_cast<>()), wobei Delphi sich da nichts nimmt (IS && TXXXX()).

Und explizit und impliziter Cast: explizit bedeutet, es muss unbedingt was angegeben werden, damit ein Cast gemacht wird. Somit ist der explizite Cast durch die Schreibweise mit neuen Type gut erkennbar. Dieser kann, muss aber keine Compilermagic beinhalten. Ein impliziter Cast wiederrum benötigt keine Angabe von Typen oder extra Code sondern die Konvertierung wird still und heimlich durchgeführt. Dieser beinhaltet meist die Verwendung von Compilermagic.

MfG
Muetze1

Cyf 8. Jan 2009 23:43

Re: Typecast or not?
 
Ok meine Definition:

Impliziter typecast:

Ein Word wird als Cardinal interpretiert, ohne dass man das selbst angibt.
ebenso Integer -> Floattyp (wobei es hier eine tatsächliche Umwandlung gibt)

Expliziter typecast:

alles, wo explizit ein Speicherbereich anders interpretiert wird
Byte(aCardinal)
Pointer(aInt)
Cardinal(P)
PMyRecord($00FFAACC)

generelle Typenumwandlung:

Funktionen die einen Typ umwandeln. :roll: IntToStr(), StrToInt, StrToFloat(), was es halt so gibt und was man auch selbst schreiben könnte.

Der Unterschied zwischen StrtoInt und einem expliziten typecast ist für mich also, ob dadurch Bytecode generiert werd, der etwas macht (streng gibt es den bei impliziten casts mitunter auch).

[Edit] roter Kasten

Meflin 10. Jan 2009 12:16

Re: Typecast or not?
 
Um die Frage noch mal hochzuholen: Behaupten kann man ja viel, aber gibt es für eure Interpretationen des Wortes Typecast auch irgendwelche unterstützenden Quellen?

quendolineDD 10. Jan 2009 12:23

Re: Typecast or not?
 
Ein Typecast ist meiner Meinung nach nichts anderes als den Inhalt der angegeben Variable, bzw. Speichers als den angegeben Typen zu interpretieren.
IntToStr etc. sind reine Typumwandlungen.

Muetze1 10. Jan 2009 12:37

Re: Typecast or not?
 
Moin!

1. Diese Umwandlung wird so genannt. Was willst du als Quelle haben? Eine Übersetzung? hier Eine Erläuterung von einer anderen Seite die das gleiche behauptet wie z.B. ich? hier.

2. @quendolineDD: Du widersprichst dir selbst. Gerade bei deinem Beispiel IntToStr() wird nicht der Speicher anders interpretiert, sondern du rufst eine Funktion auf, die das ganze verarbeitet. Der Speicherinhalt wird nicht anders interpretiert sondern dargestellt. Du teilst auf der Basis 10 Speicherstellenwert auf x viele Bytes auf, wovon eines gerade mal einen Wertebereich von '0' bis '9' nutzt. Was wird denn dort anders interpretiert?

Eine andere Interpretation des Speichers an der Stelle des Integers (und damit ein Typecast), wäre folgendes:
Delphi-Quellcode:
var
  lInt: integer;
  lStr: string;
begin
  lInt := 1234;
  lStr := string(lInt);
end;
Damit sagst du: das ist kein Integer, das ist ein String!

Und mit IntToStr() sagst du: Ich will diesen Integer bitte in der dezimalschreibweise dargestellt haben. Gleiche skannst du binär, hex oder einer sonstigen Basis haben.

MfG
Muetze1

Meflin 10. Jan 2009 12:42

Re: Typecast or not?
 
Zitat:

Zitat von Muetze1
1. Diese Umwandlung wird so genannt. Was willst du als Quelle haben? Eine Übersetzung? hier

Typecast heißt also Typumwandlung. Und was macht IntToStr? Eine Typumwandlung! Also... ist IntToStr ein Typecast?!
(Wie es eben beispielsweise auch bei Wiki steht :tongue: )


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:53 Uhr.
Seite 2 von 4     12 34      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz