Peter W.: Fragen zu Arrays in C

Moin!

Ich habe hier ein kleines Problem mit C bei dem ich nicht recht weiter weiß:

Gegeben ist eine Funktion, deren Prototyp so aussieht:

int func(int *list, size_t size)

Nun soll die Funktion folgendes machen:

  • gebe das erst Feldelement zurück, also list[0]
  • verkürze das Array list derart das list[0] entfernt wird und somit nur noch size - 1 Elemente darin enthalten sind

Folgender Code soll das ganze erreichen:

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

int func(int *list, size_t size) {
    int ret = list[0];
    int *newlist = malloc((size - 1) * sizeof(int));
    int i;

for(i = 1; i < size; i++)
        newlist[i-1] = list[i];

list = newlist;

return ret;
}

int main(int argc, char *argv[]) {
    int *list = malloc((argc-1) * sizeof(int));
    int ret;
    int i;

for(i = 1; i <= argc-1; i++) {
        printf("%d\n", atoi(argv[i]));
        list[i-1] = atoi(argv[i]);
    }

func(list, argc-1);

printf("Neuer Listeninhalt: \n");
    for(i = 0; i < argc-2; i++) {
        printf("Index %d: Wert %d\n", i, list[i]);
    }
    free(list);

return 0;
}

Leider funktioniert dies jedoch nicht - list beginnt auch nach dem Aufruf von func() noch mit dem ersten Element. Irgendeine Idee woran das liegt?

  1. Hi,

    Folgender Code soll das ganze erreichen:

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

    int func(int *list, size_t size) {

    list ist hier die Startadresse des alten Feldes.

    int ret = list[0];
        int *newlist = malloc((size - 1) * sizeof(int));

    newlist ist die Startadresse des neuen Feldes.

    int i;

    for(i = 1; i < size; i++)
            newlist[i-1] = list[i];

    Hier kopierst du die Werte aus der alten liste in die neue.

    list = newlist;

    Jetzt überschreibst du den Inhalt von list mit der neuen Adresse. Das heißt aber nicht, dass sich auch in main die Startadresse von list ändert.

    return ret;
    }

    Am einfachsten wäre es, auf newlist komplett zu verzichten und die Werte aus list zu verschieben. Also so in der for-schleife:
    list[i-1] = list[i];
    Der Nachteil an dieser Lösung ist, dass das Feld immer gleich groß bleiben würde.
    Die Lösung für dieses Problem wäre, list als Zeiger auf Zeiger zu übergeben, dann kannst du die Startadresse von list aus main ändern.
    Dein Prototyp müsste dann so aussehen:
    int func(int **list, size_t size)
    Der aufruf wäre dann:
    func(&list, argc-1);
    Damit übergibst du die Adresse der Variablen, in der die Startadresse des Feldes steht und kannst die Startadresse dadurch ändern.
    Dann müsstest du aber auch noch in der Funktion ein free für die alte Liste machen, weil du sonst immer mehr Speicher reservierst, der nicht mehr freigegeben wird.

    mfG,
    steckl

  2. Hi,

    Leider funktioniert dies jedoch nicht - list beginnt auch nach dem Aufruf von func() noch mit dem ersten Element. Irgendeine Idee woran das liegt?

    natürlich beginnt func() immer mit dem Zeiger auf das erste Element, denn der ändert sich nicht, wie der Kollege schon schrieb. Um in einer Funktion einen Zeiger zu ändern, d.h. auf einen anderen Datenbereich zeigen zu lassen, musst Du der Funktion die Adresse des Zeigers übergeben, also einen Pointer-Pointer.

    Ganz davon abgesehen würde ich dieses Vorgehen aber nicht empfehlen. Dein Programm hat ein Speicher-Leck, denn wo gibst Du den ganzen Speicher wieder frei, den Du bei jedem neuen Aufruf von list reservierst? Das ist ein no-go.

    Die Frage ist, was bezweckst Du denn eigentlich mit dem Vorgehen? Warum definierst Du Dir nicht einfach einen Zeiger auf ein int, der zunächst auf das erste Listenelement zeigt und den Du dann jeweils weiter schiebst? Das hat genau den selben Effekt. Auf den Wert kannst Du auch ganz einfach zugreifen. Und nach der Verarbeitung kannst Du den Speicherbereich sauber wieder über den Zeiger auf den Buffer-Anfang freigeben (was Du ja schon tust).

    Ciao, Stefanie