Typumwandlung
-
Hallo Leute,
mir ist nicht klar, warum man bei einer Typumwandlung den Ziel-Datentyp in Klammern vor den Wert schreibt. Diesen kann man doch auch einfach weglassen und das Programm würde doch trotzdem funktionieren oder hat diese Schreibweise eine besondere Bedeutung?
Quelle: http://www.c-howto.de/tutorial-variablen-typumwandlung.html`#include <stdio.h>
int main()
{
int i;
int c = 'A';
i = (int)c; //beispielsweise dieses "(int)"
printf("char c nach int i: %d\n", i);
i = 67;
c = (char)i; //beispielsweise dieses "(char)"
printf("int i nach char c: %c\n", i);
float f = 2.345;
i = (int)f;
printf("float f nach int i: %d\n", i);
return 0;
}
`
-
Y2K schrieb:
Hallo Leute,
mir ist nicht klar, warum man bei einer Typumwandlung den Ziel-Datentyp in Klammern vor den Wert schreibt. Diesen kann man doch auch einfach weglassen und das Programm würde doch trotzdem funktionieren oder hat diese Schreibweise eine besondere Bedeutung?
Quelle: http://www.c-howto.de/tutorial-variablen-typumwandlung.html`#include <stdio.h>
int main()
{
int i;
int c = 'A';
i = (int)c; //beispielsweise dieses "(int)"
printf("char c nach int i: %d\n", i);
i = 67;
c = (char)i; //beispielsweise dieses "(char)"
printf("int i nach char c: %c\n", i);
float f = 2.345;
i = (int)f;
printf("float f nach int i: %d\n", i);
return 0;
}
`
Es gibt übrigens spezielle C/C++ Tags, die den Code optisch noch besser darstellen:
#include <stdio.h> int main() { int i; int c = 'A'; i = (int)c; //beispielsweise dieses "(int)" printf("char c nach int i: %d\n", i); i = 67; c = (char)i; //beispielsweise dieses "(char)" printf("int i nach char c: %c\n", i); float f = 2.345; i = (int)f; printf("float f nach int i: %d\n", i); return 0; }
Zu deiner Frage: Man kann zwischen impliziter und expliziter Typumwandlung unterscheiden.
Implizite Typumwandlungen werden automatisch durchgeführt und es ist nicht notwendig diese selber vorzunehmen. Im Gegensatz dazu sind explizite Typumwandlungen notwendig, damit der Quellcode kompiliert.
Das kann der Fall sein, wenn der Compiler nicht in der Lage ist selber zu entscheiden oder um lästige Warnungen loszuwerden.
So könnte es sein, dass ein Compiler bei einer Typumwandlung von float nacht int oder von int nach unsigned int eine Warnung ausgibt, da Informationen verloren gehen können. Im Falle von float nach int wären das die Nachkommastellen und im Falle von int nach unsigned int das Vorzeichen.
-
also wenn du es weglässt macht der compiler für dich den cast = typumwandlung und du bekommst eine warnung da implizit...
du kannst ihm aber auch sagen das er das umwandeln soll (explizit) also mit der klammer usw. dann weiß der compiler das du weißt was du tust muß nichts mehr machen und du bekommst keine warnung, mir hat mal jemand gesage warnung => fehler, also schreib ichs eigentlich immer dazu, da sieht man mal das compiler auch faule hunde sind
-
In allen deinen Fällen kannst du die Typumwandlung sein lassen, es tut dasselbe. Es gibt aber auch Fälle wo das nicht so ist.
Sowas hier zum Beispiel:
char c = 'a'; printf("'a' hat die Zahl %d\n", (int)a);
Wenn du hier das (int) weg lässt kommt Blödsinn raus, weil printf ein int erwartet, das hat zum Beispiel 4 Byte, a hat aber nur 1 Byte. Also printet er a und noch 3 Bytes mit Blödsinn drin. Wenn du aber ein int draus machst, dann werden 3 leere Füllbytes hinzugefügt und printf gibt die richtige Zahl aus.
-
warnung wird zu fehler also schreib bitte deine casts aus sonst träum ich schlecht
-
Wenn ich das richtig verstanden habe geht man mit dem Cast auf Nummer sicher, dass auch wirklich der richtige Datentyp verwendet wird und es sich nicht nur z.B. um einen Tippfehler handelt, weil man beispielsweise vergessen hat den Datentyp "%c" zu ändern.
// "%c" dient als einfache Umwandlung i = 67; c = i; printf("int i nach char c: %c\n", i);
//zusätzliches "(char)" zu "%c" dient als sichere Umwandlung i = 67; c = (char)i; printf("int i nach char c: %c\n", i);
Habe ich es so richtig verstanden?
PS: Danke sadasd, für den Tipp mit den C/C++ Tags.
-
Hmm nee, mit sicher und unsicher hat das nichts zu tun. Ob nun explizit oder implizit gecastet wird ist egal, es kommt dasselbe raus. Es ist nur entscheidend wenn es keinen impliziten cast gibt.
Wenn du einem int ein float zuweist wird das float in ein int gecastet, egal ob du es explizit hinschreibst oder nicht. Wenn du hingegen printf benutzt, dann weiß keiner dass eigentlich gecastet werden muss und dann wird einfach nicht gecastet und es kommt Müll raus.
Oder ein anderes Beispiel, du willst aus einem struct bla pointer ein struct blub pointer machen. Es gibt keine implizite Regel wie man aus bla blup macht, also musst du wirklich (struct blup) vor bla schreiben.
-
nwp2 schrieb:
Hmm nee, mit sicher und unsicher hat das nichts zu tun. Ob nun explizit oder implizit gecastet wird ist egal, es kommt dasselbe raus. Es ist nur entscheidend wenn es keinen impliziten cast gibt.
wenn implizit gecastet wird hat sich der programmierer in 99,9999% der fälle keinen gedanken darüber gemacht wie und wo warum gecastet wird, dadurch entstehen fehler... man castet ja auch nicht ständig x nach y sondern macht das eher selten und dann schreibt man das dazu.
-
Ich denke, dass ich es jetzt verstanden habe.
Innerhlab von "printf" ist "(int)" notwendig damit am Ende "2" herauskommt. Ansonsten kommt ein falscher Wert heraus; hier "0".
#include <stdio.h> int main() { float a = 2.5; printf("Zahl (expliziter Cast): %d\n", (int)a); printf("Zahl (impliziter Cast): %d\n", a); return 0; }
Aber bei einem Cast außerhalb von "printf" ist es egal, ob man die Variable explizit castet. Der Wert wird nicht verfälscht. Das Ergebnis ist "2".
#include <stdio.h> int main() { int b; float a = 2.5; b=a; //einfache Zuordnung; das ist doch weder implizit noch explizit printf("Zahl: %d\n",b); return 0; }
Falls auch dieser Ansatz falsch sein sollte bitte ich um Geduld.
Bei weiteren Versuchen mir dieses Thema zu erklären wäre ich für Beispiele dankbar.Ich bedanke mich für die schnellen und hilfreichen Antworten, die bisher geleistet worden sind und bzw. noch folgen werden.
-
nwp2 schrieb:
Es gibt aber auch Fälle wo das nicht so ist.
Sowas hier zum Beispiel:
char c = 'a'; printf("'a' hat die Zahl %d\n", (int)a);
Wenn du hier das (int) weg lässt kommt Blödsinn raus, weil printf ein int erwartet, das hat zum Beispiel 4 Byte, a hat aber nur 1 Byte.
Ich glaube du verwechselst das gerade mit scanf()
-
Dein b=a enthält einen impliziten Cast von float nach int.
Du kennst doch bestimmt malloc.
malloc gibt einen void * zurück. Unter C gibt es eine implizite Regel die es erlaubt einen void * in jeden anderen Pointer umzuwandeln. Deshalb kannst du sowas schreiben:int *i = malloc(sizeof(int));
Unter C++ gibt es diese Regel nicht. Deshalb funktioniert obiger Code nicht, dort musst du explizit casten:
int *i = (int *)malloc(sizeof(int));
Hier noch ein etwas gemeines Beispiel:
#include <stdio.h> struct test{ int x; int y; }; int main(){ printf("sizeof(test): %d, 4-sizeof(test): %d\n", sizeof(test), 4-sizeof(test)); if (4-sizeof(test)<0) printf("4-sizeof(test) ist kleiner als 0\n"); else printf("4-sizeof(test) ist nicht kleiner als 0\n"); return 0; });
Die überraschende Ausgabe:
^sizeof(test): 8, 4-sizeof(test): -4
4-sizeof(test) ist nicht kleiner als 0^Das liegt daran, dass sizeof(test) ein unsigned int ist und 4 ein signed int. Die implizite Regel sagt, dass wenn signed und unsigned ints zusammengerechnet werden dass signed int in unsigned int umgecastet wird. Und ein unsigned int wird niemals kleiner als 0. printf weiß das nicht, ich habe ihm %d gesagt, das ist ein signed int, deswegen gibt er -4 aus. Der Ausdruck in der if-Klammer tut allerdings Blödsinn, weil 4-sizeof(test) 4294967292 ist und nicht -4, weil (unsigned int)-4 4294967292 ist.
Wenn man in die if-Klammer ein 4-(int)sizeof(test) schreibt funktioniert alles wie erwartet.Also halte dich an noobLolo Rat und caste möglichst immer explizit wenn du verschiedene Datentypen mischst, die impliziten Regeln tun manchmal nicht was man meint.
@Tim: Nö. scanf hat dasselbe Problem, aber ich meine schon printf.
-
nwp2 schrieb:
@Tim: Nö. scanf hat dasselbe Problem, aber ich meine schon printf.
Mit welchem Compiler auf welchem System und welcher Mondstellung kommt also bei diesem Code:
char c = 'a'; printf("'a' hat die Zahl %d\n", a);
nicht das offensichtliche heraus?
-
Hmm, komisch, irgendwie kriege ich ihn nicht dazu Blödsinn zu printen. Wahrscheinlich packt er immer 4 Bytes als Parameter auf den Stack, deswegen wirkt sich das nicht aus.
Aber das Prinzip ist klar, man gibt ihm ein Byte und er soll das als 4 Byte interpretieren, wodurch 3 undefiniert Bytes entstehen. Aber irgendwie sind die immer 0, deswegen klappts nicht.Edit: Nee, das ist es auch nicht. Er legt die Bytes einzeln auf den Stack. Ist mir gerade ein Rätsel warum das keine Probleme macht.
-
"integer promotions" klingelt da was?
-
Hmm nee, ist mir nicht klar.
Er promotet die chars nicht zu ints bis sie in printf drin sind, und danach weiß er nicht mehr dass es chars sind. Ich werde mal noch etwas rumexperimentieren.Edit: irgendwie erwarte ich, dass printf("%d", a) identisch zu printf("%d", *(int *)&a) ist, aber das ist nicht der Fall. Woher weiß der in printf dass a ein char und kein int ist, obwohl er nur ein char auf den Stack legt? Zumindest bei printf("%d %d", (char)'a', (int)5); sollte er durcheinander kommen.
Ich vermute fast der Compiler schummelt bei printf und übergibt Parameter bei printf anders als normal.
-
Du kennst doch bestimmt malloc.
malloc gibt einen void * zurück.Also "malloc" sagt mir nichts. Habe erst vor kurzem mit C angefangen und bin deshalb nicht so weit.
Mit welchem Compiler auf welchem System
Ich verwende Bloodshed Dev-C++ und Windows.
Bei mir laufen die Programme bzw. das Kompilieren problemlos, d.h. keine Fehlermeldungen.Ist mein Ansatz zum Verständnis der Typumwandlung in meinem vorherigen Post richtig?