dynamische Allokierung, malloc, calloc
-
T0bi schrieb:
Mit realloc, kannst du durch aus den Speicherplatz für ein Array dynamisch vergrößern oder verkleinern, das dieser nach der Operation nicht zwingend an der gleichen Adresse beginnt ist allerdings nicht immer der Fall. Dennoch ist dies doch dynamisch oder nicht?
Kannst Du mir das bitte mal an einem konkreten Code demonstrieren?
Also, das:int arr[100];
ist ein Array mit Platz für 100 Integerwerte. Nun zeig mir bitte, wie ich das dynamisch vergrößern/verkleinern kann.
-
Mal abgesehen von pseudodynamischen VLA, welche eh nur den Stack belasten und ohne Fehlerbehandlung auskommen müssen, ist die dynamische Speicherbelegung in C ein sehr wesentliches Kriterium, ohne das keinerlei professioneller Code auskommt.
Dynamische Speicherbelegung ist gekennzeichnet durch die Funktionen malloc,calloc,realloc und free welche immer einen Zeiger zurückliefern (und kein Array, wie bei deinem Eingangsstatement).Beispiel statischer Speicher:
#define GROESSEINBYTES 100 char array[GROESSEINBYTES]; strcpy(array,"blafasel"); puts(array);
Beispiel dynamischer Speicher:
#define GROESSEINBYTES 100 char *zeiger; zeiger=malloc(GROESSEINBYTES); strcpy(zeiger,"blafasel"); puts(zeiger); free(zeiger);
Wie du siehst, ist dynamische Speicherbelegung aufwändiger und wahrscheinlich meinte dein Prof. deshalb, du sollst es erstmal mit statischer Speicherbelegung sprich Arrays versuchen.
Und um der Frage gleich vorzubeugen: NEIN, Array und Zeiger sind NICHT dasgleiche und schon gar nicht dasselbe, nur snippetgläubige Laien behaupten dieses.
-
Wutz schrieb:
ist die dynamische Speicherbelegung in C ein sehr wesentliches Kriterium, ohne das keinerlei professioneller Code auskommt.
Janeisklar...
-
Hallo,
danke für deine Antwort, Wutz. Naja.. mein Prof. sagt uns nämlich immer, dass es "im Prinzip" keinen Unterschied zwischen Zeiger und Felder gibt. Naja, wie auch immer..
Dynamische Allokierung mit Strings haben wir bisher auch nie gemacht. Mein Prof. ist eher einer, der Mathefunktionen und -aufgaben mit C verbindet. Ich habe mittlerweile doch eine Homepage gefunden, wo Sachen wie dynamische Allokierung und so erklärt wird(http://r4r.co.in).
Von den Skripten ausgehend habe ich mal folgendes versucht und habe auch folgende Frage:
Würde ich mir mit dem Code
main(){ int size = 8; int a; a = (int)malloc(size * sizeof(int)); }
welches als Ergebnis 146903048 liefert, "146903048" Bytes freimachen?
Wenn ja, dann versteh ich es so allmählich glaub ich
Liebe Grüße,
Student.
-
Student123 schrieb:
welches als Ergebnis 146903048 liefert, "146903048" Bytes freimachen?
Zonk!
-
Student123 schrieb:
Würde ich mir mit dem Code
main(){ int size = 8; int a; a = (int)malloc(size * sizeof(int)); }
welches als Ergebnis 146903048 liefert, "146903048" Bytes freimachen?
Wenn ja, dann versteh ich es so allmählich glaub ich
Nein. Das macht so keinen Sinn. Du sagst malloc() wieviel Speicher du reservieren willst, in deinem Fall 8 mal die Größe eines int, also Platz für 8 int hintereinander im Speicher. Der Rest ist schlicht falsch. malloc gibt dir einen Zeiger auf den reservierten Speicherbereich zurück, also eine Adresse, und im Fehlerfall (z.B. nicht ausreichend Speicher frei) den NULL-Zeiger. Korrekt wäre dein Beispiel so:
int main(void){ int size = 8; int *a; a = malloc(size * sizeof(int)); if (a) { /* mache was mit a */ /* Speicher wieder freigeben */ free(a); } else { printf ("Fehler"); } }
-
Die Aussage deines Prof. beruht darauf, das in den Beispielen von Wutz die Funktionen strcpy und puts nicht mehr unterscheiden können ob die Daten zu einem array oder einem dynamischen Speicher gehören.
Die Funktionen in denen array bzw. zeiger deklariert sind können das.
Man kann Zeigern die Adresse eines Arrays zuweisen, aber nicht umgekehrt.
zeiger = array; // geht. zeiger Zeigt auf da erste Element von array array = zeiger; // geht nicht.
Beachte: array ist nicht das gleiche wie array[0].
Zudem braucht zeiger selber auch Speicherplatz.PS: Die 146903048 ist die Adresse ab der dein geforderte Speicher liegt.
mit free(a) sagst du dann: den Speicher ab Adresse 146903048 freimachen.
Wieviel SPeicher das ist erfährt free aus internen Daten von malloc.
-
Also habe ich mit meinem Code
main(){ int size = 8; int a; a = (int)malloc(size * sizeof(int)); }
ab der Adresse "146903048" 8x4=32 Bytes reserviert?
-
Genau.
-
Student123 schrieb:
Würde ich mir mit dem Code
main(){ int size = 8; int a; a = (int)malloc(size * sizeof(int)); }
welches als Ergebnis 146903048 liefert, "146903048" Bytes freimachen?
Komplett falsch.
malloc liefert einen Zeiger zurück, du solltest den obigen Text nicht nur lesen sondern auch umsetzen, du hast nämlich die Adresse des von malloc gelieferten belegten Speicherbereiches einem int zugewiesen, das ist natürlich Unsinn.
-
Ok, alles klar.
Jetzt stehen noch einige Fragen aus. Wenn ich mit malloc arbeite wie im ebigen Beispiel, muss ich es in einem Feld, Pointer oder in einer Variable abspeichern?
Wutz hat eben nämlich a als Pointer deklariert aber als Variable genutzt.
Wenn ich mit einem Feld arbeiten muss und angenommen ich will das Feld i mit i * i füllen, wie müsste ich da vorgehen?
-
Vom Prinzip hast du das verstanden, aber dein Code hat noch Fehler.
Zeiger werden in C mit dem * davor deklariert.main(){ int size = 8; int *a; // a ist ein Zeiger, *a ist ein int a = (int *)malloc(size * sizeof(int)); *a = 4; // in das erste Element von a wird eine 4 geschrieben. *(a+1) = 5; // in das zweite Element von a wird eine 5 geschrieben. // :warning: Der Compiler weiß wie groß ein int ist und zählt schon richtig weiter (hier +(1*4)) }
* ist der Dereferenzierungs-Operator
-
#define ANZAHLELEMENTE 8 int i,*zeiger = malloc(ANZAHLELEMENTE*sizeof(int)); for( i=0;i<ANZAHLELEMENTE;++i ) zeiger[i] = i*i; for( i=0;i<ANZAHLELEMENTE;++i ) printf("\n%d",zeiger[i]); free(zeiger);
-
aber benutzt du beim deklarieren den Pointer a(also
und weiter unten beim Code wo das mit malloc gemacht wird das einfache a?
-
Nur zur Klarstellung:
Das geht beides.zeiger[i] ist gleichbedeutend mit *(zeiger+i)
Was wieder Verwirrung über den Unterschied zwischen Zeigern und Arrays stiften wird.
-
hmm.. ok.
main(){ int size = 8; int *ptr; int i; int grenze; *ptr = (int)malloc(size * sizeof(int)); grenze = size * sizeof(int); for(i = 0; i<grenze; i++){ ptr[i] = i * i; } }
so würde ich size * sizeof(int) Felder mit i * i füllen?
-
Beim deklarieren sagst du *int a; a ist ein Zeiger auf ein int. Oder zum merken: *a ist ein int.
malloc liefert dir einen Zeiger (auf void) und den musst du dann zuweisen: a = malloc(..);
int *a, a = malloc(...); *a = 5; printf("Der Inhalt von %p ist %d\n", a, *a); free(a);
----------------------
Gerade noch gesehen:
Nein eben nicht:main(){ int size = 8; int *ptr; int i; int grenze; // FALSCH *ptr = (int)malloc(size * sizeof(int)); // *ptr ist ein int ptr = (int *)malloc(size * sizeof(int)); // ptr ist der Zeiger auf int // FALSCH grenze = size * sizeof(int); grenze = size ; // Der Compiler weiß wie groß ein int ist! // Du hast nur 8 int, keine 32 for(i = 0; i<grenze; i++){ ptr[i] = i * i; // Beim Zugriff achtet der Compiler auf die richtigen Offsets }
}
-
Hm, ok alles klar. Ich nehme das nun einfach mal so hin. Ich muss eine Aufgabe mit malloc lösen, die wie folgt beschrieben ist:
Erzeugen Sie in einem Programm zu einer Folge von Zahlen, die vom Benutzer
einzugeben sind, das Zahlendreieck, in dem sich ab der zweiten Zeile jede Zahl als
Summe der darüberliegenden Zahl und deren rechter Nachbarzahl ergibt.
Die Anzahl der zu behandelnden Zahlen ist vom Benutzer einzugeben, dann ist ein
Feld geeigneter Größe dynamisch (mit malloc oder calloc) zu erzeugen.Das war jene Aufgabe, wo der Prof von mir wollte dass ich es erst statisch mache. Die dynamische Version gibts dann am Montag.
-
Hey,
machen wir doch einmal gleich da weiter, wo wir aufgehört haben. Unzwar versuche ich grade das obrige Problem zu lösen.
Ich habe folgenden Code geschrieben:
//Deklaration int size = 0; int *zahlen; int i; //Eingabe der Größe printf("Wieviele Zahlen?\n"); scanf("%d",&size); //Reservierung der Größe zahlen = (int *)malloc(size * sizeof(int)); //Eingabe der Zahlen for(i = 0; i<size;i++){ printf("Bitte geben Sie %d Zahlen ein:\n",size); scanf("%p",zahlen[i]); }
Aber ich bekomme nach Eingabe der ersten Zahl ein "Segmentation fault".
Wieso?
-
1. musst du an scanf Adressen (Zeiger) übergeben
2. Was willst du denn mit "%p" bei scanf erreichen?
Probier mal %i oder %d.scanf("%i",&zahlen[i]); //oder scanf("%i",zahlen+i);