Verständnisfrage zu Pointern



  • Hallo zusammen ...

    Mir ist eben etwas aufgefallen, was ich nicht verstehe!

    Ich kann problemlos folgenden Quellcode schreiben und ausführen:

    char *C="a";
    printf("%c",*C);
    

    Mir wird ein "a" ausgegeben.

    Wenn ich aber schreibe:

    int *I=1;
    printf("%d",*I);
    

    Bekomme ich die Fehlermeldung beim Kompilieren "error C2440: 'Initialisierung': 'int' kann nicht in 'int *' konvertiert werden".

    Warum klappt das Eine, aber das Andere nicht???

    Danke für euere Hilfe! 🙂



  • Mandel schrieb:

    ...
    Bekomme ich die Fehlermeldung beim Kompilieren "error C2440: 'Initialisierung': 'int' kann nicht in 'int *' konvertiert werden".

    Warum klappt das Eine, aber das Andere nicht???...

    Steht doch da!

    😉
    Vorab: Willst Du wirklich mir C weitermachen? Oder nicht doch lieber C++ programmieren?

    Wenn es bei C bleiben soll: Dafür gibt es ein eigenes Unterforum, bei dem Du glücklicher werden wirst.

    Wenn nicht: Nimm für Strings das, was dafür gemacht ist: std::string.
    Das vereinfacht die Sache in 1000 Situationen und würde bei Dir einfach zu

    std::string C="a";
    std::cout << C;
    

    werden.

    @Dein Code:
    Was ist ein "char"? -> EIN Buchtstabe. (nicht zwei, nicht drei, sondern: EINER!)
    Wie kennzeichnet man in C und C++ EINEN Char-Literal? -> 'a'.
    (Merke: Einfache Anführungsstriche)
    Wenn Du es also richtig "gemacht" hättest (also so, wie bei Deinem int-Beispiel), hättest Du schreiben müssen:

    char *C='a';
    

    .... und hättest dieselbe Fehlermeldung erhalten wie bei Deinem int-Beispiel.
    DENN: "char*" bedeutet "Zeiger auf einen Buchstaben" - und der kann halt nicht mit einem "Buchstaben" initialisiert werden, sondern nur mit einer Speicheradresse, an der hoffentlich auch ein Buchstabe zufinden ist.
    Zu Zeigern gibt's hier&im Internet schon genug nachzulesen, aber nur soweit: Dein Haus ist auch nicht dasselbe wie Deine Adresse.

    Mit "a" kennzeichnet man eine ZeichenKETTE (die in diesem speziellen Fall halt nur 2 Zeichen (1 Buchstabe + 1 Stringendekennzeichen) umfasst).
    Wie gesagt: Wenn Du wirklich mit Zeichenketten arbeiten möchtest, sind C++ und std::string Deine Freunde (und Helfer) 😉
    Wenn Du Lust hast, den Umgang mit Zeigern zu lernen (die auch in C++ sehr sinnvoll sind), würde ich Dir vorschlagen, das an anderen Beispielen zu üben.

    Gruß,

    Simon2.



  • int *I = 1;
    

    Thats a negative! Ein Zeiger zeigt auf eine Adresse!

    int a = 3;
    int *I = &a;
    


  • Vielen Dank erstmal für euere Antworten!

    Ich hab mir das auch schon so gedacht, bzw. schon mal so ähnlich gelesen.
    Es ist ja so, dass der Zeiger auf eine Adresse zeigt. Und die muss ja erstmal für eine Variable reserviert sein.
    Also mit "int i;" reserviere ich dann ja eine Adresse für einen Int. Und auf die kann ich dann mit "I=&i" von zeigen. Durch printf("%d",*I); kann ich dann den Inhalt der Adresse ausgeben.

    Aber was ich leider immer noch nicht verstanden habe:
    Warum klappt das mit "char *C="a""?
    Damit das klappt muss doch dann auch erstmal eine Speicheradresse reserviert werden, ein Wert reingeschrieben werden und dann auch noch der Zeiger drauf gerichtet werden. Das alles übernimmt ja dann der Ausdruck. Sollte das bedeuten, dass due "a" schon Speicher reserviert wird?

    Entschuldigung übrigens für mein schreckliches Mischmasch aus C und C++ 🙄



  • Mandel schrieb:

    Entschuldigung übrigens für mein schreckliches Mischmasch aus C und C++ 🙄

    Bisher ist das kein Mischmasch sondern reines C. Du solltest dich allerdings entscheiden (und Bescheid sagen) was von beidem du möchtest. Im Fall C wird der Thread hier dann ins ANSI-C-Forum verschoben, im Fall C++ darfst du dir dann anhören was du alles nicht machen solltest und wie das in C++ soooo vieeeel besser geht 😉



  • dein Beispiel: in c++

    char *p;
        int  *pi;
        char c = 'A';
        int i  = 1;
        pi    = &i;
        p     = &c;
        cout<<*p<<*pi;
    


  • Mandel schrieb:

    Warum klappt das Eine, aber das Andere nicht???

    Weil in einem Fall der Typ des Initialisierers "passt" und im anderen Fall nicht.

    char * pc1 = "a";  // OK, "a" ist vom Typ const char[2]
    char * pc2 = 'a';  // Fehler! Typ von 'a' ist char und nicht char*
    int  * pi  = 1;    // Fehler! Typ con 1 ist int und nicht int*
    

    Zeiger kannst Du entweder mit 0 Initialisieren (wird dann ein Nullzeiger) oder mit einer Adresse eines Objekts vom "richtigen" Typen. Um die Adresse eines Objektes zu bekommen, musst Du den Adress-operator ( & ) benutzen. Literale wie 1 , 'a' oder 3.14159265 besitzen keine Addresse. Deswegen kannst Du auch nicht das hier schreiben:

    int * pi = &2;  // Fehler! [c]int[/c]-Literale haben keine Adressen!
    

    Du musst also erst irgendwo einen int anlegen, damit ein Zeiger darauf zeigen kann:

    int k = 23;
    int * pi = &k;  // OK
    

    Soweit sogut.

    String-Literale spielen eine besondere Rolle, weil sie eine Adresse besitzen. Das String-Literal "a" ist vom Typ const char[2] -- also ein Array aus zwei unveränderliche Zeichen, 'a' und '\0'. Dieses Array sitzt wirklich irgendwo im Speicher (da kümmert sich der Compiler drum) und man kann sich die Adresse des ersten Zeichens so holen:

    const char* pc = "Hallo, Welt!";
    

    Das funktioniert so, weil es in C und C++ "array-to-pointer decay" gibt. Dabei wird automatisch ein Zeiger erzeugt, der auf das erste Element zeigt. Das Prinzip ist das gleiche wie in diesem Fall

    int array[10];
    int * pi = array;      // ist equivalent
    int * pi = &array[0];  // zu dem hier
    

    String-Literale spielen noch eine zweite Sonderrolle. In C sind solche Literale nämlich nicht const, obwohl man sie trotzdem nicht verändern darf. Aus Gründen der C-Kompatibilität kann man also auch Zeiger vom Typen char* (ohne const) mit String-Literalen initialisieren.

    Gruß,
    SP



  • Mandel schrieb:

    Das alles übernimmt ja dann der Ausdruck. Sollte das bedeuten, dass due "a" schon Speicher reserviert wird?

    So ähnlich. Die Zeichenkette "a" steht irgendwo im Speicher und durch Deinen Ausdruck wird der Zeiger 'C' dort drauf gerichtet.


  • Mod

    Mandel schrieb:

    Warum klappt das mit "char *C="a""?

    Weil "a" (mit ") kein char ist. 'a' (mit ') wäre vom Typ char. Sachen zwischen doppelten Anführungszeichen gelten als Zeichenkette und da gibt es eine Konvertierung zu char*, da char* in C die übliche Art und Weise ist, mit Zeichenketten umzugehen. Mein C++ Compiler gibt übrigens bei

    char *C="a"
    

    zu Recht die Warnung

    warning: deprecated conversion from string constant to 'char*'
    

    aus.

    edit: Woah, da war ich wohl viel zu langsam beim Antworten.



  • Ich glaub jetzt hab ichs!

    Vielen Dank für euere Mühe...



  • Du kannst es wissen.
    String-Literale "bla" sind eine Ausnahme. Fertig.


Anmelden zum Antworten