malloc und array



  • Hi,

    ich habe ein Problem mit der Allozierung von Speicher bei Arrays. Warum muß man hier 2 mal für das erste Element Speicher allozieren?

    int *ptr;
        ptr       = malloc(sizeof(int));
        ptr[0]    = (int)malloc(1 * sizeof(int));
        ptr[1]    = (int)malloc(1 * sizeof(int));
    
        ptr[0]    = 123;
        ptr[1]    = 456;
        printf("out %i %i\n", ptr[0], ptr[1]);
    

    Denn ptr und ptr[0] sollten doch auf die selbe Speicheradresse zeigen oder habe ich da was falsch verstanden?

    Wenn ich im Code den int-Pointer durch einen Pointer auf ein struct ersetze kriege ich den Code nicht mal kompiliert:

    struct address *addresses;
    ...
    
    addresses    = (struct address *)malloc(sizeof(struct address));
    addresses[0] = (struct address *)malloc(sizeof(struct address)); 
    addresses[1] = (struct address *)malloc(sizeof(struct address));
    addresses[2] = (struct address *)malloc(sizeof(struct address));
    

    Ich möchte eigentlich dynamisch in einer For-Schleife Speicher allozieren, denn ich weiß nicht wieviele Elemente ich überhaupt aus der Datei lese.

    Viele Grüße,
    foobar



  • foobar23 schrieb:

    Warum muß man hier 2 mal für das erste Element Speicher allozieren?

    Muss man nicht. Du hast da was gründlich mißverstanden. So alloziert man Speicher für n Elemente:

    // type steht sinngemäß für alle möglichen Typen (ausser void)
    type *foo;
    foo = malloc(n * sizeof(*foo)); // _kein_ Cast nötig
    
    // checken ob malloc() funktioniert hat blabla
    
    foo[0]   = bar;
    foo[1]   = bar;
    // ...
    foo[n-1] = bar; // Das letzte Element des reservierten Speicherbereichs
    
    // lustige Dinge machen
    
    free(foo); // Speicher freigeben
    


  • Muss man nicht. Du hast da was gründlich mißverstanden. So alloziert man Speicher für n Elemente:

    Das ist mir klar. Ich möchte aber dynamisch Speicher allozieren. Ungefähr so:

    void readFile(char *fileName, struct address *addresses, int *counter)
    {
        FILE *file = fopen(fileName, "r");
        if (NULL == file)
        {
            printf("Could not open file %s", fileName);
            return;
        }
    
        char line[100];
    
        //int size  = 3* sizeof(struct address);
    
        int i=0;
        while (fscanf(file, "%s",line) != EOF)
        {
            // hier soll für jedes struct Speicher angefordert werden
            addresses[i] = (struct address *)malloc(sizeof(struct address));       
            strcpy(addresses[i].name, strtok(line, ";"));
            strcpy(addresses[i].street, strtok(NULL, ";"));
            strcpy(addresses[i].city, strtok(NULL, ";"));
            i++;    
        }
        *counter = i;
        fclose(file);
    }
    

    Das muß doch irgendwie funktionieren oder?



  • kleiner verstaendnistest:

    1. beschreibe den sinn und das verhalten von malloc(), free() und realloc()!
    2. beschreibe sinn und verhalten von sizeof()! vergleiche auch sizeof() auf pointer und sizeof auf arrays!
    3. erklaere die "." und "->" operatoren!

    ich hoffe, die beantwortung (oder nicht-beantwortung) der fragen bringt dir klarheit 🙂



  • das verstehen die wenigsten auf anhieb, darum eine kurze erklaerung:

    int *ptr;
        ptr = malloc(sizeof(int));
    

    ...holt speicher fuer ein int und laesst "ptr" darauf zeigen
    ueber "ptr" kannst du wie mit einem array darauf zugreifen:
    ptr[0] liefert dir ein int
    ptr[1] existiert nicht

    was du eigentlich willst ist ein array von pointern:

    int **ptr;
       ptr= (int**)malloc(sizeof(int*) * anzahl);
    

    danach liefert dir ptr[0]..ptr[anzahl-1] jeweils ein int* - diesen kannst du dann wieder "speicher zuweisen":

    ptr[0]= (int*)malloc(anzahl2 * sizeof(int));
       ptr[1]= (int*)malloc(anzahl2 * sizeof(int));
       ...
    

    dadrin hast du dann jeweils "platz" fuer "anzahl2" ints:

    int i;
       int *ptr1= ptr[1]; // ein int* aus ptr[...]
       i= ptr1[5];  // int aus int*[]
       i= ptr[1][5]; // oder direkt
    

    problem: du musst vorher wissen, wieviele int* du benoetigst.
    darum moechtest du wahrscheinlich dynamische datenstrukturen benutzen...



  • Erstmal Danke für eure Antworten 🙂

    hellihjb schrieb:

    das verstehen die wenigsten auf anhieb, darum eine kurze erklaerung:

    int *ptr;
        ptr = malloc(sizeof(int));
    

    ...holt speicher fuer ein int und laesst "ptr" darauf zeigen
    ueber "ptr" kannst du wie mit einem array darauf zugreifen:
    ptr[0] liefert dir ein int
    ptr[1] existiert nicht

    was du eigentlich willst ist ein array von pointern:

    Aber ich kann doch auch durch sizeof(int) * N Speicher für N Elemente allozieren. Warum brauche ich dann ein Array von Pointern?

    hellihjb schrieb:

    problem: du musst vorher wissen, wieviele int* du benoetigst.

    Genau das weiß ich eben nicht.

    hellihjb schrieb:

    darum moechtest du wahrscheinlich dynamische datenstrukturen benutzen...

    Hmm, dann muß ich eben eine verketette Liste implementieren, wenn es nicht anders geht.

    Was ich eigentlich machen möchte ist folgendes:
    Ich möchte Daten aus einer CSV-Datei in eine Array von Structs einlesen um dann damit arbeiten zu können. Daher wollte ich eben die Datei zeilenweise einlesen und dann für jede neue Zeile eben Speicher allozieren. Aber leider funktioniert das nicht so wie ich mir das vorgestellt habe. Wie macht man das denn normalerweise in C?

    Viele Grüße,
    foobar



  • du machst das:

    addresses = malloc(sizeof(struct address) * N);
    

    dann hast du das selbe wie ein array:

    struct address addresses[N];
    

    zum vergroessern so:

    tmp = realloc(addresses, sizeof(struct address) * neuesN);
    if (!tmp) { puts("fehler!"); free(addresses); return -1;}
    addresses = tmp;
    

    edit: hellihjb, so weit ich das erkenne, wollte er keine mehrdim. arrays.



  • Ich mach das immer so:

    void *Locate(void *ptr, int size)
    {
      if (size == 0)
        { if (ptr)
              free(ptr);
          return(0);
        }
      if (ptr)
          ptr = realloc(ptr, size);
        else
          ptr = malloc(size);
      if (ptr == 0)
        { printf("FEHLER: ptr = Locate() = 0\n");
          getch();
        }
      return(ptr);
    }
    
    int main()
    {
      char *buffer;
    
      buffer = 0;
      /* Speicher besorgen */
      buffer = (char *)Locate(buffer, 33);
      /* vergroessern / verkleinern */
      buffer = (char *)Locate(buffer, 128);
      /* freigeben */
      buffer = (char *)Locate(buffer, 0);
    }
    


  • kek, in deiner Locate sind mehrere sinnlose stellen:
    * realloc(NULL,...) ist erlaubt, wirkt wie malloc()
    * realloc(!=NULL, 0) ist erlaubt, gibt NULL zurueck
    * realloc(NULL, 0) scheint erlaubt zu sein, gibt != NULL zurueck
    * free(NULL) ist erlaubt, macht nichts
    * ein/ausgabe hat in speicheralloziierungsfunktionen nichts verloren
    * getch() ist kein ANSI C. benutze getchar()
    * return ist keine funktion. du kannst (und evtl solltest) die klammern weglassen



  • Danke für eure Hilfe 🙂

    Ich habe es jetzt so gelöst:

    struct address *readFile(char *fileName, struct address *addresses, int *counter)
    {
        addresses  = malloc(1 * sizeof(struct address));
        FILE *file = fopen(fileName, "r");
        if (NULL == file)
        {
            printf("Could not open file %s\n", fileName);
            fclose(file);
            return addresses;
        }
    
        char line[100];
    
        int i=0;
        while (fscanf(file, "%s",line) != EOF)
        {
            if (i > 0)
            {
                int s = ((i+1) * sizeof(struct address));
                addresses = realloc(addresses, s);
            }
    
            strcpy(addresses[i].name, strtok(line, ";"));
            strcpy(addresses[i].street, strtok(NULL, ";"));
            strcpy(addresses[i].city, strtok(NULL, ";"));
            i++;    
        }
        *counter = i;
        fclose(file);
        return addresses;
    }
    


  • c.rackwitz schrieb:

    kek, in deiner Locate sind mehrere sinnlose stellen:

    okokok...


Anmelden zum Antworten