Zeiger und Strings



  • Hallo !
    Ich habe nur eine ganz kurze Frage, konnte dazu leider aber nicht wirklich was finden.

    Ist soetwas hier erlaubt :

    char* str;
    
    str = "c-plusplus.net";
    

    Es kommt kein Fehler beim Kompilieren oder Ausführen, aber eigentlich sollte man ja vorher Speicher reservieren wenn man so etwas macht, oder verstehe ich das Falsch ??

    Richtig wäre es ja wenn man es so macht:

    char str[128];
    
    strcpy(str,"c-plusplus.net");
    

    Bitte klärt mich auf, ob man Zeiger einfach so einen String zuweisen darf.

    Danke



  • hey,

    also meiner Meinung nach sollte das kein Problem sein, du kannst den "String" ja auch direkt bei der Deklaration initialisieren!

    char* str={"Hier der String"};
    

    Bei deiner Zweiten Möglichkeit bildest du ja ein Char Array von 128 Feldern und in der ersten Variante wird die Größe automatisch gewählt.

    Also korrigiert mich wenn ich daneben liege, aber ich denke das kannst du ruhig so machen!

    Gruß
    Sascha



  • char* str;
    str = "c-plusplus.net";
    

    Ja, so kann man das machen. Der Compiler reserviert automatisch den Speicherplatz und ist auch noch so freundlich eine Null dran zu hängen.



  • Ein String der Form "string" ist ein sog. Stringliteral. Es handelt sich dabei um Readonly Speicher. Mit

    const char *ro = "read only string";
    

    zeigt ro auf ein Stringliteral. Du darfst aber diesen String nicht verändern, wenn du es versuchst, dann kracht das Programm.

    Mit

    char rw[] = "read write string";
    

    Wird ein Arrays rw angelgt und mit dem Inhalt des Stringliterals "read write string" initialisiert. Das angelegte Array hat die Größe strlen("read write string") + 1 (wegen abschließendes \0-Zeichens). "read write string" bleibt read-only, jedoch der Speicher im rw (wo eine Kopie des Literals sich befindet) darf verändert werden.

    Mit

    char rw[128];
    strcpy(rw, "again read write");
    

    ist es dasselbe, nur dass du den Inhalt von rw mit der Funktion strcpy belegst.



  • Danke für die vielen Antworten.

    Das ich mit char[128] ein Array bilde weiß ich.

    Es geht mir nur darum ob man einen Zeiger deklarieren darf, und _nach_ der Deklaration als einen "beliebig" großen String initialisieren darf.

    Den Modifier const kenn ich auch 🙂 ging mir aber lediglich um die Deklaration und um die Initialisierung.

    Das angelegte Array hat die Größe strlen("read write string") + 1 (wegen abschließendes \0-Zeichens). "read write string" bleibt read-only, jedoch der Speicher im rw (wo eine Kopie des Literals sich befindet) darf verändert werden.

    Nur nebenbei, "read write string" bleibt read-only, weil es im Programm "hardgecoded" ist ?? Das hab ich bis jetzt noch nie gehört, das ein String read only bleibt. Das ich das char-Array ändern kann, ist mir klar (außer es ist auch const.)



  • ,,,, schrieb:

    Es geht mir nur darum ob man einen Zeiger deklarieren darf, und _nach_ der Deklaration als einen "beliebig" großen String initialisieren darf.

    ja, das ist korrekt, aber man muss an dieser Stelle zwisschen dem Zeiger und dem Inhalt unterscheiden, worauf der Zeiger zeigt. Du initialisierst den Zeiger, weil er auf eine gültige Speicheradresse zeigt, jedoch der Speicherbereich worauf der Zeiger zeigt, ist read-only. Und sowas geht nur bei Strings, weil Literale ihre Speicheradresse zurückgeben. Folgender Code ist ungültig und dafür gibt es auf zumindest eine Warnung

    int *zeiger = 7;
    

    denn damit würdest du den Zeiger so initialisieren, dass er auf die Adresse 0x7 zeigt und das ist etwas ganz anders, als dass der Inhalt worauf der Zeiger zeigt mit 7 intialisiert wird.

    ,,,, schrieb:

    Nur nebenbei, "read write string" bleibt read-only, weil es im Programm "hardgecoded" ist ??

    Ja, das kann man so sehen. Stringliterale haben eigentlich den Typ 'const char*'.

    ,,,, schrieb:

    Das hab ich bis jetzt noch nie gehört, das ein String read only bleibt. Das ich das char-Array ändern kann, ist mir klar (außer es ist auch const.)

    den Inhalt des Literals kannst du natürlich nicht ändern. Den Inhalt des Arrays schon, aber der Inhalt des Arrays ist auch eine Kopie des Literals. Das kann man daran erkennen:

    void foo()
    {   
        ((char*)"hello")[0] = 0;
        "hello"[0] = 0;
    }
    

    Und gcc meint

    e.c: In function 'foo':
    e.c:4: error: assignment of read-only location
    

    Und Zeile 4 ist nun mal "hello"[0] = 0;. Ohne die 4. Zeile würde der Code kompilieren, aber an der Stelle würde das Programm auch abschmieren, weil "hello" konstant ist.



  • Ahh, danke !!

    Jetzt glaub ich hab ich es verstanden 🙂

    Vielen Dank für diese ausführliche Erklärung! Der Thread kommt gleich in die Favoriten 🙂


Anmelden zum Antworten