Aufruf von malloc für char Arrays



  • Hallo zusammen,

    ich möchte gerne folgenden Zusammenhang verstehen. Beim Bereitstellen von Speicher für die Struktur Node, reicht offenbar der unten ersichtliche Aufruf von malloc und mir ist nicht vollkommen klar, wieso. In Node habe ich itsName lediglich als Pointer auf einen Wert vom Typ char definiert, also als erstes Element eines Arrays mit Elementen vom Typ char. Wieso ist nun klar, wieviel Speicher durch einen Aufruf von malloc reserviert werden muss, obwohl zu dem Zeitpunkt noch gar nicht feststeht, wie lang das char-Array werden wird. Hätte ich statt "char *itsName" eine konstante Länge angegeben, also etwa "char itsName[50]" könnte ich das nachvollziehen... Im Übrigen wird das Programm ohne Warnungen übersetzt und arbeitet auch für größere Array-Längen korrekt.

    Im Übrigen bin ich ziemlicher Neuling beim Programmieren, weswegen eine etwas "geerdete" Erläuterung höchst willkommen wäre :-)))

    #include <stdio.h>
    #include <stdlib.h>
    
    struct Node
    {
        char *itsName;
        struct Node *itsSuccessor;
    };
    
    int main(int argc, char **argv) 
    {
        struct Node *N = (struct Node*)malloc(sizeof(struct Node));
        N->itsName = "Text";
        printf("%s\n", N->itsName);
        return 0;
    }
    

    Grüße
    pinwheel



  • Bei einem String-Literal (bei dir: "Text") wird schon beim Programmstart Speicher reserviert, so daß die Zuweisung völlig korrekt ist. Du brauchst (bzw. darfst!) ja auch für dieses String-Literal den Speicher nicht freigeben.
    Gespeichert wird daher in der Node Membervariablen 'itsName' auch nur die Anfangsadresse des String-Literals (nicht der String selbst).

    Genauer:
    Alle String-Literale werden vom Compiler automatisch in den Data-Bereich der EXE abgelegt, und beim Programmstart wird einfach der gesamte Data-Bereich in den Speicher kopiert (so daß deren Adressen dann zur Verfügung stehen).



  • Das char-Array* wird nicht in der struct gespeichert.

    Da ist nur der Zeiger.

    Diesen Zeiger lässt du (Zeile 13) auf das Stringliteral "Text" zeigen.

    *Du brauchst da auch kein Array, sondern nur einen Speicherbereich.
    Der kann auch über malloc besorgt werden oder auch ein Stringliteral sein.



  • Th69 schrieb:

    Genauer:
    Alle String-Literale werden vom Compiler automatisch in den Data-Bereich der EXE abgelegt, und beim Programmstart wird einfach der gesamte Data-Bereich in den Speicher kopiert (so daß deren Adressen dann zur Verfügung stehen).

    Was genau ist der Data-Bereich (ich arbeite unter Linux, daher kenne ich keine *.exe :-)))? Bisher sind mir nur die Begriffe Stack und Heap über den Weg gelaufen. Ich habe mal versucht, die Initialisierung des Knotenlabels an eine Funktion "setNode" zu übergeben. Da lokale Daten nach Abarbeitung der Funktion ja wieder vom Stack gelöscht werden, das Label aber in main() noch korrekt ausgegeben werden kann, soll das also bedeuten, dass der String "Text" irgendwo im Heap abgelegt wird und die Struktur Node lediglich einen Zeiger auf das dortige erste Element speichert. Ist das so richtig?

    Im Allgemeinen hätte ich ja erwartet, dass ich manuell auch für den String "Text" zunächst einmal mit malloc Speicher anfordern muss, aber offenbar ist das überflüssig.

    #include <stdio.h>
    #include <stdlib.h>
    
    struct Node
    {
        char *itsName;
        struct Node *itsSuccessor;
    };
    
    struct Node *setNode()
    {
        struct Node *N = (struct Node*)malloc(sizeof(struct Node));
        N->itsName = "Text";
        return N;
    }
    
    int main(int argc, char **argv) 
    {
        struct Node *N = setNode();
        printf("%s\n", N->itsName);
        return 0;
    }
    




  • pinwheel schrieb:

    Was genau ist der Data-Bereich (ich arbeite unter Linux, daher kenne ich keine *.exe :-)))?
    Bisher sind mir nur die Begriffe Stack und Heap über den Weg gelaufen.

    Dann solltest Du mal deinen Horizont erweitern.

    Nur weil Dateien nicht die Endung .exe haben koennen sie sie dennoch "executable" sein.

    Initialisierte Variable werden weder auf dem Stack, noch auf dem Heap abgelegt.
    Das kannst Du auch unter dem Link von DirkB nachlesen.



  • Th69 schrieb:

    Alle String-Literale werden vom Compiler automatisch in den Data-Bereich der EXE abgelegt, und beim Programmstart wird einfach der gesamte Data-Bereich in den Speicher kopiert (so daß deren Adressen dann zur Verfügung stehen).

    DirkB schrieb:

    http://en.wikipedia.org/wiki/Data_segment

    Das Datensegment ist für initialisierten RW-Speicher. Kein Compiler packt dort Stringliterale rein, außer solche, die zum Initialisieren eines statischen Arrays verwendet werden. Stringliterale kommen, zusammen mit anderen Konstanten, in das Textsegment (bzw. .rodata).



  • pinwheel schrieb:

    Was genau ist der Data-Bereich (ich arbeite mit ISO-C, daher kenne ich keine *.exe :-)))?

    ftfy :p


Log in to reply