Pointer-Typumwandlung



  • Guten Tag,
    Ich habe eine Frage zum cast Operator, und zwar folgendes Beispiel:

    char c,*c_ptr;
    int *i_ptr;
    
    c_ptr=&c;
    i_ptr=(char *)c_ptr;
    

    Was mich hier wundert, dass wir char * schreiben.(Wurde in der Vorlesung so geschrieben, hab ich mich verschrieben?) Meiner Logik nach, müssten wir i_ptr=(int *)c_ptr; schreiben, da wir ja die Variable c_ptr nach einem Integer Wert umwandlen möchten.

    Eine andere Frage(egal ob da jetzt CHAR oder INT steht..):

    char c,*c_ptr;
    int *i_ptr;
    
    c='x';
    printf("%c \n",c);//kommt 'x' raus-OK
    printf("%d \n",c);//kommt 120 raus-OK
    
    c_ptr=&c;
    printf("%c \n",*c_ptr);//kommt 'x' raus-OK
    printf("%d \n",*c_ptr);//kommt 120 raus-OK
    
    i_ptr=(int *)c_ptr;
    printf("%c \n",*i_ptr);//kommt 'x' raus-OK
    printf("%d \n",*i_ptr);//kommt -1074184072 raus-Hä??
    

    Ja hier das Problem.. Meiner Logik nach wird in der Character Variable ja der Ascii Code als Inhalt gespeichert. (hier:120). So jetzt über gebe ich der Variable c_ptr die SpeicherAdresse von der Variable C. Will ich das jetzt einem Integer Pointer(i_ptr) weitergeben, muss ich es ja ins Integer Datenformat umwandlen. Aber der Inhalt bleibt ja unverändert.? Was man auch erkennt da ja 'x' rauskommt. Aber wenn ich jetzt die Dezimale Schreibweise auf die i_ptr zeigt rausgebe, müsste ich wieder 120 bekommen, was aber nicht der Fall ist...

    Kann mir da jemand bitte Helfe,

    Vielen dank!



  • newinc schrieb:

    Aber wenn ich jetzt die Dezimale Schreibweise auf die i_ptr zeigt rausgebe, müsste ich wieder 120 bekommen, was aber nicht der Fall ist...

    Du behauptest ja, dass i_ptr auf einen 4 Byte großen Bereich zeigt, der einen Integerwert darstellt - vorausgesetzt, auf Deinem System ist ein int 4 Byte groß.
    Denn das ist das, was ein Zeiger auf einen Integer tut, und bei i_ptr handelt es sich ja um so einen.



  • Sorry aber das verstehe ich jetzt nicht, auch nach mehrmaligem lesen nicht. 😕



  • newinc schrieb:

    Sorry aber das verstehe ich jetzt nicht, auch nach mehrmaligem lesen nicht. 😕

    Das Verhalten Deines Programmes ist undefiniert.

    Wenn Du einen int pointer dereferenzierst, holt sich der Compiler bzw. das Programm 4 Bytes aus dem Speicher. Je nach Speichermodel kann dies aber auch eine andere Größe sein.

    printf erwartet bei %c und bei %d ebenfalls 4 Bytes auf dem Stack, wertet aber bei %c nur das niedrigste Byte aus, deshalb kommt das erwartete Ergebnis, bei %d werden aber wirklich alle 4 bytes ausgewertet und Du kontrolliert aber nur eines.

    mfg Martin



  • printf erwartet bei %c und bei %d ebenfalls 4 Bytes auf dem Stack, wertet aber bei %c nur das niedrigste Byte aus, deshalb kommt das erwartete Ergebnis, bei %d werden aber wirklich alle 4 bytes ausgewertet und Du kontrolliert aber nur eines[/quote]
    Verstehe ich das richtig, dass also nur das Lower Byte "angeschaut" wird ? Und was kann ich dagegen tun,damit die 4 Bytes gelesen werden ? Mit einer erneute Cast Umwandlung im Printf selbst haut es nicht hin.



  • printf erwartet bei %c und bei %d ebenfalls 4 Bytes auf dem Stack, wertet aber bei %c nur das niedrigste Byte aus, deshalb kommt das erwartete Ergebnis, bei %d werden aber wirklich alle 4 bytes ausgewertet und Du kontrolliert aber nur eines

    Verstehe ich das richtig, dass also nur das Lower Byte "angeschaut" wird ? Und was kann ich dagegen tun,damit die 4 Bytes gelesen werden ? Mit einer erneute Cast Umwandlung im Printf selbst haut es nicht hin.



  • newinc schrieb:

    Und was kann ich dagegen tun,damit die 4 Bytes gelesen werden ?

    Nicht mit einem int-Zeiger auf ein char zeigen.



  • Bashar schrieb:

    newinc schrieb:

    Und was kann ich dagegen tun,damit die 4 Bytes gelesen werden ?

    Nicht mit einem int-Zeiger auf ein char zeigen.

    Ja..aber das haben wir so in der Vorlesung behandelt..



  • newinc schrieb:

    Bashar schrieb:

    newinc schrieb:

    Und was kann ich dagegen tun,damit die 4 Bytes gelesen werden ?

    Nicht mit einem int-Zeiger auf ein char zeigen.

    Ja..aber das haben wir so in der Vorlesung behandelt..

    Du solltest den Dozenten auswechseln, wenn er Dir so 'nen Schrott zeigt.



  • newinc schrieb:

    Bashar schrieb:

    newinc schrieb:

    Und was kann ich dagegen tun,damit die 4 Bytes gelesen werden ?

    Nicht mit einem int-Zeiger auf ein char zeigen.

    Ja..aber das haben wir so in der Vorlesung behandelt..

    Erklär mir doch mal bitte, wie das Behandeln von irgendwas in einer Vorlesung dazu führt, dass man etwas macht, was Ergebnisse hat, die man nicht will. Ist mir völlig unverständlich.

    Mal ganz unabhängig davon, ob die Vorlesung irgendwas taugt, was bei weitem nicht immer der Fall ist.



  • Ich kann ihn schlecht rausschmeissen 😛

    Aber ne andere Sache, über diesem Beispiel steht noch:

    EInem Zeiger vom Typ void* dürfen Zeiger eines anderen Datentyps zugewiesen werden und umgekehrt.

    Ich sehe zwar nicht dass hier ein Zeiger auf void zeigt aber vielleicht wollte er da was verdeutlichen ?



  • Zeigercasts sind was für Profis, d.h. also Leute, die wissen was sie tun, also NICHTS für
    - Anfänger
    - Lehrer
    - Fachbuchautoren
    - C++ler

    Zeigercasts decken die Warnungen des Compilers zu (der Compiler hat immer recht), und das ist nahezu immer Unsinn.
    Erkläre doch mal mit eigenen Worten: was willst du mit einem Zeigercast Sinnvolles erreichen (außer, die Compilerwarnungen zuzudecken):
    Worin soll der Sinn bestehen, eine Referenz auf einen Speicherbereich für einen ganz konkreten Typ bewusst auf einen inkompatiblen Typ umzuwandeln?
    Wenn du solch einen manipulierten Zeiger verwendest, d.h. ihn dereferenzierst, baut der Compiler dafür Code, der von einem ganz anderen Typ im gleichen zuvor genannten Speicherbereich ausgeht, und das ist schon allein wegen des Alignments (außer bei Casts in Richtung *char*,void*) UB, und beim Datenzugriff dann erst recht.
    void* ist ein Sonderfall, heißt aber auch nicht, den sinnlos zu casten.

    char c,*c_ptr;
    int *i_ptr;
    
    c_ptr=&c;  /* OK, weil & ein Synonym für 'Zeiger auf' ist */
    i_ptr=(char *)c_ptr; /* Schrott, da c_ptr bereits den Typ 'char*' besitzt, was soll ein Cast auf denselben Typ bringen? */
    

    Für einen Aha-Effekt kannst du ja mal versuchen, einen void* zu dereferenzieren, und dann vielleicht noch überlegen, warum der Compiler sich weigert, sowas zu machen.



  • newinc schrieb:

    Aber ne andere Sache, über diesem Beispiel steht noch:

    EInem Zeiger vom Typ void* dürfen Zeiger eines anderen Datentyps zugewiesen werden und umgekehrt.

    Ich sehe zwar nicht dass hier ein Zeiger auf void zeigt aber vielleicht wollte er da was verdeutlichen ?

    Nein, sonst hätte er das gemacht. Casts nach und von void sind auch nicht nötig, die Umwandlung macht der Compiler auch ohne Cast:

    int x;
    void *p = &x; /* kein Cast, implizite Umwandlung */
    int *q = p;   /* ------------ " ---------------- */
    

    (Ergänzung: in C++ ist void* -> anderer Zeigertyp nicht implizit möglich. )



  • Vielleicht soll das ganze zu einem besonderen Lerneffekt führen.

    Aus der -1074184072 kann man folgendes schließen:

    -1074184072 (dez) = BFF94078 (hex).
    Die 4 Byte dieser Zahl stehen in dieser Reihenfolge im Speicher: 78 40 F9 BF (Little Endian).
    Somit haben wir an der 1. Position, d.h. an der Adresse, wohin deine Pointer zeigen, das Byte 78 (hex) = 120 (dez) = 'x'.
    Die anderen 3 Byte wurden nicht initialisiert und besitzen daher zufällige Werte.



  • Danke an alle für eure Hilfe, hat mir Licht ins dunkle gebracht! 😃
    @BFF94078 :
    Interessant!Werde mir das mal genauer anschauen!
    Danke!

    -newinc


Log in to reply