Malloc, was bringt macht folgender Quellcode?



  • Was genau meinst du?

    "... darfst auf den ptr zeigt. "
    Soll der Satz vielleicht lauten "... darfst, der auf den ptr zeigt"?

    Ja das weiß ich, ich reseviere Speicher um etwas ablegen zu können.

    Was macht aber das Programm?

    Ich definiere zu Beginn einen Wert, der wie ich verstanden hab die Anzahl meiner Arrays festlegt, in diesem Fall würde man glaube ich Pointer-Array sagen.
    Daraufhin definiere ich die Größe der zu allokierenden (zu resevierenden) Elemente. Aber wo kommt dieser Schritt im Programm vor, wo wirkt sich jetzt die Variable "size" aus?

    Memory teilte mir ja mit, dass die rechnung wäre ANZAHL*GRÖßE=ERGEBNIS

    Also wenn ich sage Anzahl= 4 und Größe= 2, ergibt das 8

    Hab ich 8 Bytes für meinen Kompletten Pointer reseviert?

    Also hab ich jetzt:

    ptr[] = 8 Bytes

    oder

    ptr[0] = 8 Bytes
    ptr[1] = 8 Bytes
    ptr[2] = 8 Bytes
    ptr[3] = 8 Bytes
    ptr[4] = 8 Bytes

    oder

    ptr[0] = 2 Bytes
    ptr[1] = 2 Bytes
    ptr[2] = 2 Bytes
    ptr[3] = 2 Bytes
    ptr[4] = 2 Bytes
    (Diese version geht davon aus dass die Variable "anzahl" nur auch wirklich die Anzahl der Arrays bestimmt und sonst nix, die andere Variable "size" (=2 Bytes), die ich angegeben hab sind dann für die Zahlen, die der Anwender eingibt reseviert.)

    Also das ist meine Auffassung vom Ganzen. Jetzt die Frage, was ist davon falsch Interpretiert und was ist richtig???????????????? 😕



  • malloc reserviert eine vorgegebene Anzahl Bytes und gibt einen Zeiger auf diesen neu allokierten Speicherbereich zurück. Was daran so schwer zu verstehen?
    Was du mit dem Zeiger machst, ist egal für malloc.
    Du weist einem int-Zeiger diesen Zeiger zu. Damit zeigt dein int-Zeiger nun auf den o.g. Speicherbereich. Was du jetzt mit diesem int-Zeiger machst, ist egal für malloc.
    Du weist dem Speicherbereich durch Durchlaufen des int-Zeigers Werte zu, dabei füllst du jeweils sizeof(int) Bytes. Das gibt undefiniertes Verhalten, falls du mit einer dieser Zuweisungen an den int-Zeiger über den mit malloc zuvor allokierten Bereich hinausschreibst.
    Deshalb ist die Aufgabenstellung mit variabler Angabe der Elementgröße soweit schwachsinnig, solange der eingegebene Wert ungleich sizeof(int) ist.



  • Das Verständnisproblem wird wohl einfach nur an dem Faktor size liegen? Das ist aber recht einfach, es ist quatsch diese Größe abzufragen, wie du ja auch schon richtig festgestellt hast. Warum das im Programm gemacht wird, weiß wohl nur dein Professor. Aber zur Erklärung. Alle Daten sind im Speicher nur ein paar Bytes. Wie viele sagt dir sizeof. Was man mit den Daten machen darf, dass weißt nur du und der Compiler. Der Computer weiß es nicht. malloc macht nun nichts anderes, als ein paar Bytes zu reservieren, wo du deine ints speichern kannst. Der einzige Grund, warum du size angeben musst ist, weil malloc auch nicht weiß, was du dort speichern willst. malloc ist das auch so ziemlich egal. Du musst nur darauf achten, dass wenn du ein Feld von 1000 ints speichern willst, du 1000*sizeof(int) anforderst und du dann später auch nur die Elemente von 0 bis 999 nutzt. Beim Zugriff erledigt dieses sizeof(int) nämlich der Compiler. Weil er weiß ja, dass du einen int-Zeiger hast.

    int * foo;
    
    foo = foo + 1; // hier rechnet er in Wirklichkeit foo + sizeof(int)
    


  • Der Compiler kopiert in deinem Beispiel also die Adresse von 1 und hängt es dem Pointer an? Also wird dort die Binärezahl 1 kopiert.

    Kann man vielleicht auch aus deinem Beispiel folgendes machen?

    int * foo=NULL;
    
    foo = foo + 1; // hier rechnet er in Wirklichkeit foo + sizeof(int)
    

    Ich würde das irgendwie so machen ,weil ich die befürchtung hätte, dass irgendwas in meinem Pointer schon stehen kann, irgendeinene zufällige Adresse oder so.

    Liege ich da irgendwie richtig?



  • Ich glaube du liegst nicht richtig. malloc gibt dir einen Zeiger auf einen Speicherbereich zurück. Dort kannst du dann deine ints ablegen:

    AAAABBBBCCCC
      ^
      Bsp zeigt auf Adresse 42
    

    A, B und C wären dann deine ints, jeweils 4 Bytes. int *foo; würde hier jetzt den Wert 42 haben. Wenn du nun foo++; machst, dann zeigt foo automatisch auf B. Also foo = foo + 4; [sizeof(int)=4]. Bei einem Feld von short (2Bytes), würde der Zeiger bei foo++, 2 Bytes weiter wandern. Das nennt man Zeigerarithmetik. malloc gibt übrigens einen typenlosen Zeiger zurück (void*) mit diesem kannst du nicht rechnen, weil er keinen Typ hat und demzufolge auch keine Größe für den Typen.
    Merken musst du dir also. malloc kennt keine Typen, deswegen immer Bytes. Ein Zeiger kennt seinen Typ, deswegen kümmert er sich selber um die richtige Größe.



  • GW1nner schrieb:

    Der Compiler kopiert in deinem Beispiel also die Adresse von 1 und hängt es dem Pointer an? Also wird dort die Binärezahl 1 kopiert.

    Nein. Der Compiler nimmt den Wert von foo und addiert dazu 4 (weil hier int 4 Byte hat).

    GW1nner schrieb:

    Ich würde das irgendwie so machen ,weil ich die befürchtung hätte, dass irgendwas in meinem Pointer schon stehen kann, irgendeinene zufällige Adresse oder so.

    Da steht auch irgend etwas drin, aber zu einem NULL-Pointer braucht man nichts addieren.
    NULL ist die Kennzeichnung für einen ungültigen Zeiger.

    int * foo;
    int   bar[10];
    
    foo = bar; // jetzt zeigt foo auf bar[0] (dem Anfang von bar)
    printf ("foo zeigt auf %p\", foo);
    
    foo = foo + 1; // jetzt zeigt foo auf bar[1] 
    printf ("foo zeigt auf %p\", foo);
    

    Besser?



  • Folgende Beispiele werden dich sicher noch mehr verwirren, aber schau es dir mal in Ruhe an.

    http://codepad.org/fxOLregx



  • Wenn du folgendes beantworten kannst, solltest du es eigentlich verstanden haben. Ausgabe des Programms?

    #include <stdio.h>
    
    char  char_feld[3];
    short short_feld[3];
    int   int_feld[3];
    
    int main(void)
    {
      printf("%d\n", sizeof(char_feld));
      printf("%d\n", sizeof(short_feld));
      return 0;
    }
    

    int habe ich jetzt mal weg gelassen. Aber wie würde die Ausgabe aussehen, wenn noch zusätzlich die Zeile mit int vorhanden wäre, auf einem 64Bit-System?



  • Im Programm werden die größen der einzelnen Arrays ausgegeben.

    Im ersten sind es

    Char: ??? ka wieviel bytes ein char hat 8? 8x3?
    Short : 2x3 = 6 Bytes
    int : 4x3 = 12 Bytes

    Hab ich es gecheckt? 😕

    Um es nochmal revü zu passieren,
    ich benutze malloc nur dazu, Speicher zu resevieren bzw. freizuhalten. Es muss also nicht unbedingt alles ausgenutzt werden?

    Wie kann man das dann dynamisch gestalten so, dass nur soviel Speicherplatz reseviert wird, wieviel der Anwender auch wirklich verbraucht durch seine Eingaben?

    Etwas verstehe ich das glaub ich jetzt, das erinnert etwas an Assembler, da finde ich es aber wesentlich einfacher Speicher für eine Eingabe frei zu machen 🙂



  • Im Programm werden die größen der einzelnen Arrays ausgegeben.

    Im ersten sind es

    Char: ??? ka wieviel bytes ein char hat 8? 8x3?
    Short : 2x3 = 6 Bytes
    int : 4x3 = 12 Bytes

    Hab ich es gecheckt? 😕

    Um es nochmal revü zu passieren,
    ich benutze malloc nur dazu, Speicher zu resevieren bzw. freizuhalten. Es muss also nicht unbedingt alles ausgenutzt werden?

    Wie kann man das dann dynamisch gestalten so, dass nur soviel Speicherplatz reseviert wird, wieviel der Anwender auch wirklich verbraucht durch seine Eingaben?

    Etwas verstehe ich das glaub ich jetzt, das erinnert etwas an Assembler, da finde ich es aber wesentlich einfacher Speicher für eine Eingabe frei zu machen 🙂



  • Die Standard *alloc Funktionen garantieren mindestens die übergebene Anzahl Bytes allokiert zu haben (wenn sie nicht NULL zurückgeben). Wieviel in Wirklichkeit belegt werden, ist unspezifiziert.



  • GW1nner schrieb:

    Etwas verstehe ich das glaub ich jetzt, das erinnert etwas an Assembler, da finde ich es aber wesentlich einfacher Speicher für eine Eingabe frei zu machen

    Welche Funktion soll das denn in Assembler machen?
    Wenn du vorher weißt wie viel Speicher du brauchst, kannst du den auch statisch belegen.

    malloc holt den Speicher vom OS. Und den teilen sich alle Programme auf deinem Rechner.

    GW1nner schrieb:

    Char: ??? ka wieviel bytes ein char hat 8? 8x3?

    Das ist mit das zweite was man nach "Hallo Welt!" aus einem C-Buch/Kurs lernt.



  • Ja es wurde mal erwähnt aber ich merk mir ja nicht alles was die Profs erzählen 🙂

    Bei Assembler muss man halt auch erstmal die maximal mögliche Eingabeweite festlegen, jedoch kann man daraufhin auf einen anderen Label die tatsächliche größe der eingabe kopieren.

    Es ist ja so, dass im eax Register immer die Information steht, wie viel der Anwender tatsächlich eingegeben hat. Nach einem Interrupt kann man dass dan abfragen.


Anmelden zum Antworten