Malloc und Structs



  • Eigentlich habe ich auch so begonnen einfach die char mit einer bestimmten länge zu deklarieren. Drufte ich aber aus einem mir unbekannten Grund nicht.

    Die Aufgabenstellung zieht wahrscheinlich darfauf ab mir den Befhel malloc genauer anzuschauen. Hab ihn nur noch nicht ganz verstanden.
    struct Liste {int Prio; char *name; struct Liste *pNext;};
    muß auf jeden Fall bleiben!



  • strcpy(root->name, "Hallo");
    

    hier liegt der Fehler!

    du musst erst Speicher führ den namen reservieren - erst mit strlen die Länge des Strings feststellen und dann speicher reservieren:

    int Sting_Laenge = strlen("Hallo"); // angenommen strlen liefert Stringlänge ohne Nullterminierungszeichen
    root->name = (char*)malloc(String_Laenge+1); // sizeof(char) ist immer gleich 1 +1 ist für das Nullterminierungszeichen
    strcpy(root->name, "Hallo");
    


  • #include <string.h>
    #include <malloc.h>
    
    struct List {
      int Prio;
      char *Name;
      List *Next;
    } *root;
    
    setListItemData(List *Item, int p, char *Name, List *NextItem) {
      Item->Name = (char*) malloc((strlen(Name)+1) * sizeof(char));
      strcpy(Item->Name, Name);
      Item->Prio = p;
      Item->Next = NextItem;
    }
    
    int main(void) {
      setListItemData(root, 1, "Name!", NULL);
      return 0;
    }
    

    EDIT:
    Verdammt, zu langsam 😡



  • feigling schrieb:

    strncpy(root->name, "Hallo", sizeof(root->name));

    😮 nein, so nicht! sizeof liefert die Anzahl der Bytes, nicht die Länge des Strings. Dafür gibt es strlen, außerdem kopiert strncpy die ersten n Zeichen von Hallo und nicht sizeof(root->name)!

    feigling schrieb:

    root->name = strdup("Hallo");

    strdup ist nicht ANSI C

    Swordfish schrieb:

    #include <string.h>
    #include <malloc.h>
    
    struct List {
      int Prio;
      char *Name;
      List *Next;
    } *root;
    
    setListItemData(List *Item, int p, char *Name, List *NextItem) {
      Item->Name = (char*) malloc((strlen(Name)+1) * sizeof(char));
      strcpy(Item->Name, Name);
      Item->Prio = p;
      Item->Next = NextItem;
    }
    
    int main(void) {
      setListItemData(root, 1, "Name!", NULL);
      return 0;
    }
    

    EDIT:
    Verdammt, zu langsam 😡

    schon mal daran gedacht, dass malloc NULL zurückliefern kann? Und malloc wird in stdlib.h definiert, also stdlib.h statt malloc.h. In C brauchst du nicht zu casten und sizeif(char)==1. Außerdem ist das C++, kein C, denn struct falsch benutzt wird.

    typedef struct tmpList {
      int Prio;
      char *Name;
      struct tmpList *Next;
    } List;
    
    List *root;
    


  • supertux schrieb:

    feigling schrieb:

    strncpy(root->name, "Hallo", sizeof(root->name));

    😮 nein, so nicht! sizeof liefert die Anzahl der Bytes, nicht die Länge des Strings. Dafür gibt es strlen, außerdem kopiert strncpy die ersten n Zeichen von Hallo und nicht sizeof(root->name)!

    Und was genau wollen wir haben ? Genau. Die Bytes also die Größe von root->name. Wie willst du da mit strlen arbeiten ? "strlen(root->name)" ist undefiniert und "strlen("Hallo");" nicht zu gebrauchen, weil "Hallo", bzw der String auch größer sein kann als die Größe von root->name. strncpy kopiert entweder den ganzen String, wenn die Länge (wie hier "hallo") kleiner gleich ist wie sizeof(root->name), also bis zum '\0' von "hallo" oder es kopiert sizeof(root->name) Zeichen, also genau so lang wie root->name ist. Ka, was du hier zu meckern hast O_o
    Das einzige, worauf man achten muss ist, wenn die Länge von dem Text größer ist als die Größe von root->name, dass dann '\0' nicht in root->name reinkopiert wird, also der string kein Ende hat.

    "außerdem kopiert strncpy die ersten n Zeichen von Hallo und nicht sizeof(root->name)! "

    Ja, aber maximal sizeof(root->name) Zeichen, wenn die Länge des Strings größer ist -> kein buffer overflow.



  • Gut, in diesem Fall kann das funktionieren; strncpy leifert aber kein 0-terminierendes String.



  • supertux schrieb:

    schon mal daran gedacht, dass malloc NULL zurückliefern kann? Und malloc wird in stdlib.h definiert, also stdlib.h statt malloc.h. In C brauchst du nicht zu casten und sizeif(char)==1. Außerdem ist das C++, kein C, denn struct falsch benutzt wird.

    typedef struct tmpList {
      int Prio;
      char *Name;
      struct tmpList *Next;
    } List;
    
    List *root;
    

    Also zu 'schon mal dran gedacht' kann ich nur sagen spar's dir - Ja, natürlich kann jedwede Speicheranforderung mit einem NULL-Zeiger enden; Sollte man auf jeden fall überprüfen, also korrekterweise jeden Pointer nach Speicheranforderung gegen NULL prüfen:

    if(!pFoo = malloc(10)) {
      // throw exception
    }
    

    Schon mal dran gedacht, daß der Definitionsort von malloc() von der jeweiligen IDE abhängig sein könnte!? Isses denn nicht trotzdem ANSI-C?

    Zur definition meiner struct:
    Bin es aus Borland C - geht ziemlich rüde mit den ANSI Standards um - so gewohnt. Tut mir leid, gelobe besserung.



  • Ich habe leider immer noch ein problem mit den Pointern in meinem Programm. Anscheind geht da was bei der übergabe in die Unterprogramme schief.
    Bitte seit nachsichtig mit meinem Leichtsinn, ich lerne das ja grad erst alles 🙂
    Hier mal mein ganzer Quelltext:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    struct Liste {int Prio; char *name; struct Liste *pNext;};
    struct Liste *root;
    struct Liste *ptmp;

    //zu 3.
    void PrintElem(struct Liste *Tail)
    {
    printf("Prioritaet %d\nName %s\nPointer %p\n", Tail->Prio, Tail->name, Tail->pNext);
    }

    //zu 6.
    void PrintElems(struct Liste *Tail)
    {
    while(&Tail != NULL )
    {
    printf("Prioritaet %d\nName %s\nPointer %p\n", Tail->Prio, Tail->name, Tail->pNext);
    Tail = Tail->pNext;
    }
    }

    int main(void)
    {
    //zu 1. und 2
    printf("Aufgabe 1 + 2\n");
    int lSize;
    struct Liste Liste1={9, "Hansmeier", NULL};
    lSize = sizeof(struct Liste);
    printf("Groesse %d\nName %s\nPrioritaet %d\nPointer %p\n",lSize,Liste1.name, Liste1.Prio, Liste1.pNext);
    //zu 3.
    printf("\nAufgabe 3\n");
    PrintElem(&Liste1);

    //zu 4.
    printf("\nAufgabe 4\n");
    root = (struct Liste 😉 malloc(sizeof(struct Liste));
    root->name = (char 😉 malloc(sizeof("Aufgabe4")+1);
    strcpy(root->name, "Aufgabe4");
    root->Prio=1;
    root->pNext=NULL;
    PrintElem(&root);

    //zu 5.
    printf("\nAufgabe 5\n");
    ptmp = (struct Liste 😉 malloc(sizeof(struct Liste));
    ptmp->name = (char 😉 malloc(sizeof("Aufgabe5")+1);
    strcpy(ptmp->name, "Aufgabe5");
    ptmp->Prio=3;
    ptmp->pNext=&root;
    root=ptmp;

    //zu 6.
    printf("\nAufgabe 6\n");
    PrintElems(&root);

    system("PAUSE");
    return 0;
    }



  • Hab a paar Fehler gefunden. Ich referenziere immer alles (damit will ich die Adresse übergeben). das ist aber anscheinend falsch. Ohne '&' funktioniert alles. Warum?



  • Zumlin schrieb:

    Hab a paar Fehler gefunden. Ich referenziere immer alles (damit will ich die Adresse übergeben). das ist aber anscheinend falsch. Ohne '&' funktioniert alles. Warum?

    1. Benutze CPP tags 😡

    Tail zeigt schon auf irgendeine Speicherstelle. &Tail liefert zurück, welchen Werte die Stelle speichert, auf die Tail zeigt. Du willst aber überprürufen, ob Tail NULL ist, d.h. du kannst nicht NULL mit den Inhalt vergleichen ...


Anmelden zum Antworten