[C/C++] Ich verzweifle an Pointern...(malloc etc.)

Dieses Thema im Forum "Programmierung & Entwicklung" wurde erstellt von Dragonknight, 11. November 2009 .

Schlagworte:
  1. 11. November 2009
    Ich verzweifle an Pointern...(malloc etc.)

    Hi mal wieder,

    bin momentan dran Pointer zu lernen. Grundprinzip hab ich denke verstanden. Nur muss ich jetzt "malloc" usw können. habe hier mal nen sourcecode aus nem buch aus dem ich lerne:

    Code:
    #define MAX_ZAHL 100
    
    void main() {
     double *memptr,*hilf;
     int i;
     memptr = (double *) malloc(MAX_ZAHL *
     sizeof(double));
     hilf = memptr;
     if(memptr == NULL) {
     printf("\nNicht genuegend Speicher!");
     exit(1);
     }
     printf("\nSpeicher fuer %i double-Werte ok!\n",
     MAX_ZAHL);
     for(i=0; i<MAX_ZAHL; i++)
     *hilf++=4711.0+i;
     for(i=0; i<MAX_ZAHL; i++)
     printf("\t%.0f ",memptr[i]);
     free(memptr);
     printf("\nSpeicherplatz wieder freigegeben!");
    }
    so jetzt steig ich da aber fast vorne und hinten nicht durch...

    folgende fragen:
    was bedeutet das hier:
    memptr = (double *) malloc(MAX_ZAHL *
    sizeof(double));
    warum steht das (double *) in klammern? warum MAX_SIZE * ??? kann mir wer das mal komplett ausführlich erläutern?

    wann schreibe ich eigl beim zuweisen = und wann == ?

    wofür steht diese zeile? *hilf++=4711.0+i;
    warum 2 for schleifen hintereinander?

    ich verzweifel noch an dem kompletten quelltext und an C sowiso ;(
     
  2. 11. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    So hab mal kurz ein paar kommentare reingeschrieben. Ich rate dir aber dazu dich mal bei galileo computing in das thema einzulesen (google) !!!

    Code:
    #define MAX_ZAHL 100 --> MAX_ZAHL wird jetz vom precompiler in 100 geändert
    [...]
     memptr = (double *) malloc(MAX_ZAHL *sizeof(double)); // (double*) ist ein expliziter typecast zum typ double* und mit malloc wird dann MAX_ZAHL (also 100) mal der speicher reserviert der für einen double gebraucht wird
     
     if(memptr == NULL) { // abfrag -> ist memptr Null? dann is was falsch gelaufen!
     
     [...]
     for(i=0; i<MAX_ZAHL; i++) //erste schleige zum beschreiben
     *hilf++=4711.0+i;
     for(i=0; i<MAX_ZAHL; i++) //zweite schleife zur ausgabe
     printf("\t%.0f ",memptr[i]);
     free(memptr); // speicher freigeben
    
    
     
  3. 11. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    Hmm ist schon ne weile her bei mir...
    Malloc war doch in C dass was in C++ dann "new" ist.. (und free = delete)....

    Also, korrigiert mich bitte wenn ich was falsches sage...

    Code:
    memptr = (double *) malloc(MAX_ZAHL *
     sizeof(double));
    memptr ist ein double pointer, der bekommt also einen pointer zugewiesen

    (double *) <--- Konvertiert den nachstehenden Code in einen pointer der zu einer double zeigt.
    malloc <-- reserviert die angegebene Zahl (an Bytes) auf dem Heap.
    MAX_ZAHL * sizeof(double) = 100 * 8 (Bin mir nicht sicher wie groß ne double ist)

    Also steht da quasi
    Code:
    memptr = (double *) malloc(800);
    Also beinhaltet der pointer memptr jetzt die Adresse zum ersten reservierten byte...
     
  4. 11. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    (double *) ist ein Cast des Ergebnisses von malloc (void-pointer) zu einem pointer auf double
    ich denke mal du meinst MAX_ZAHL: in dem fall soll malloc so viel speicher reservieren, wie für 100 (--> über konstante festgelegt) double-werte benötigt wird.
    mit anderen worten, das ganze ist dann ein array mit 100 double-werten, könnte auch mit double memptr[100]; geschrieben werden, liegt dann aber halt in nem anderen speicherbereich

    Zuweisungen finden immer mit = statt, Vergleiche immer mit == !

    der double-pointer hilf ist ein zeiger auf den anfang des double-arrays

    in Kombination mit der for schleife, die drumrum läuft, wird jedes element des oben erzeugten double-arrays mit dem wert gefüllt, von 4711.0 bis 4810.0 --> 100 elemente

    in der zweiten schleife wird der jeweilige wert im array ausgegeben
    so schlimm isses doch garnich
     
  5. 11. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    @coksnuss jo double sind 8byte (also 64 bit ;-) )
     
  6. 11. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    danke erstmal für eure schnellen antworten. hab jetzt bestimmt 15 minuten mit der nase auf euren antworten gelegen ^^
    verstehe es schon ein bisschen besser, aber muss mir das denke morgen abend nochmal in ruhe mit neuer energie (und hoffnung^^) anschauen.

    eine frage grad vorab noch:
    dieses (double *)... es macht aus dem ergebnis von malloc einen doublepointer.... aber malloc dient doch dazu speicher freizuschaufeln.... und das ergebnis dient doch nur dazu zu sagen wie viel (also die 800 byte). warum also einen pointer draus machen? malloc macht grundsätzlich einen void pointer und der wird hier in double umgewandelt?

    wenn wer noch was zu ergänzen hat oder vlt auch noch tipps hat immer her damit
     
  7. 11. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)


    bei sowas hilft die C referenz, hier ein kleiner auszug
    Code:
    Return Value
    On success, a pointer to the memory block allocated by the function.
    The type of this pointer is always void*, which can be cast to the desired type of data pointer in order to be dereferenceable.
    If the function failed to allocate the requested block of memory, a null pointer is returned.
    
    Quelle: malloc - C++ Reference
     
  8. 12. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    Um hier mal ein Missverständnis aufzuklären:

    Bei C ist es nicht nötig, den Pointer, der von malloc zurückgegeben wird auf double* zu casten. Man hätte eigentlich einfach schreiben können:
    Code:
    memptr = malloc(MAX_ZAHL * sizeof(double));
    Bei C stellt das kein Problem dar, da malloc einen void*-Pointer zurückliefert und in C ein void*-Pointer auf jeden beliebigen Datentyp zeigen kann.

    Wenn du allerdings in C++ programmierst und malloc() aufrufst, dann musst du casten. Aber in C++ sollte man eh new verwenden.
     
  9. 12. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    Hey!

    Was ich noch ergaenzen will:

    Warum braucht man eigentlich malloc ()?!

    Das ist eine gute Frage, da man ja auch um ein Array von z.B. double*-pointern zu erstellen, das auch einfach so machen koennte:
    Code:
    double *darray[ANZAHL] = { NULL };
    Das tolle an malloc () liegt daran, dass es dynamisch Speicher alloziieren kann. Wenn du in einem normalen Programm das so wie oben schreibst, muss ANZAHL immer eine Konstante sein.

    Beispiel:
    Der User will X Werte eingeben und dann auf irgendeine Weise ausgerechnet haben. Du kannst jetzt natuerlich via ANZAHL eine Obergrenze der Anzahl der Werte, die der User eingeben darf, angeben. Das macht das Programm aber statisch und unflexibel. Mit malloc () jedoch kannst du dir dann den Speicher, den du in diesem Fall brauchst, reservieren! Wenn der User 20 eingeben macht, brauchst du 20 Stueck eines Datentyps, also reservierst du diesen. Wenn der naechste User 250 Eingaben macht, reserviert malloc () dir Speicher fuer 250 Eingaben. Auf diese Weise musst du dein Programm an bestimmten Stellen nicht beschraenken.

    Als kleiner Tipp:
    Am besten jeden Speicher, den du per malloc () reservierst mit memset () auf Standard-Werte setzen:
    Code:
    char *ptr = malloc (ANZAHL * sizeof (<datatype>));
    memset (ptr, 0, ((ANZAHL * sizeof (<datatype>)) - 1));
    Beispiel am Datentype 'char' (sizeof(char) = 1; deshalb lass ich das mal weg):
    Code:
    char *ptr = malloc (ANZAHL);
    memset (ptr, '\0', (ANZAHL - 1));
    // '\0' = 0
    Wenn du das nicht machst, koennte es sein, dass strlen () oder andere Funktionen komische Ergebnisse liefern, da dein Char-Array eventuell nicht 0-terminiert ist.

    Ich bin mir uebrigens nicht mehr sicher, ob das '-1' noetig ist. Da muss ich mal mein Valgrind spaeter anwerfen und das ueberpruefen. Es ist auf jeden Fall sicher, mal -1 anzugeben

    Mfg,

    Kolazomai
     
  10. 12. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    Richtig.

    memset() aber die genaue Größe übergeben, also nicht ANZAHL-1, wie in Kolazomai's Beispiel, sondern ANZAHL, denn wenn ich n Bytes reserviere, und ich dann alle Felder mit 0 initialisieren will, dann muss ich auch n Bytes angeben.

    Grüße.

    // Edit:

    Eben getestet (C++, deswegen die Cast's):

    Code:
    #include <iostream>
    
    using namespace std;
    
    int main( void )
    {
     char *t = (char*)malloc(15); // 15 Bytes anfordern
    
    
     memset(t, 0, 14); // 14 Bytes auf 0 setzen
     cout << "Nach memset() mit 14 Bytes: \n";
     for(unsigned i=0; i<15; i++)
     {
     cout << hex << "0x" << (int)t[i] << ' '; // Komischerweise zeigt er chars nicht hexadezimal an, mit int allerdings schon ;) net weiter beachten.
     }
    
     memset(t, 0, 15); // 15 Bytes auf 0 setzen
     cout << "\n\nNach memset() mit 15 Bytes: \n";
     
     for(unsigned i=0; i<14; i++)
     {
     cout << hex << "0x" << (int)t[i] << ' ';
     }
     cout << endl;
    
     free((void*)t);
    
     cin.ignore(cin.rdbuf()->in_avail());
     cin.get();
    
     return 0;
    }
    
     
  11. 12. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    okay dankeschön. denke/hoffe ich habs jetzt besser verstanden

    bws an alle sind raus
     
  12. 13. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    ganz ehrlich? pointer sind der grund warum ich mich ned richtig an c/c++ rantrau. klar verstandenen hab ich das ganze schon, n pointer zeigt auf den speicher, aber daraus resultiert für mich ein einziges kaos bei parametern und ein haufen "WTF's" im code ^^

    dazu kommt noch (wie bei java) ein haufen an verschiedenen libs/namespaces wo man als anfänger ~30min mit der doku/google beschäftigt is wenn man was bestimmtest braucht...
    wobei man bei c/c++ aber dazusagen muss, dass man wenigstens die ganzen libs lesen und verstehen kann (wenn man von den ganzen "WTF's" mal absieht).

    sorry für OT, aber das musste jetz mal raus
     
  13. 13. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    Also das mit den Pointern ist wirklich nicht soo kompliziert Klar muss man ein wenig aufpassen, aber man hat halt viel mehr Einfluss auf sein Programm.

    Und das mit der Bibliothek stimmt so auch nicht. Die Stdlib von Java ist um ein Vielfaches größer als die von C oder C++, also findet man sich mit der Stdlib von C/C++ eigentlich sehr schnell zurecht.
     
  14. 13. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    Najo. Zeiger sind am Anfang immer ziehmlich Zeitintensiv, dahinter muss man erstmal steigen. Danach ist es aber ziehmlich einfach zu verstehen und sogar sehr nützlich einsetzbar, bei falscher Benutzung allerdings auch tötlich. *g*

    Die Bibliotheken sind, wie Pyro schon sagte, ziehmlich kompakt - eigentlich.
    Es gibt nicht allzuviele, und wenn du etwas suchst, dann musst du nur die Bibliothekennamen kennen, denn dann weißt du ganz genau wo du zu suchen hast, und wo nicht.
     
  15. 13. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    Pointer sind wie die Kupplung beim Autofahren... Am Anfang tut man sich ein bisschen schwer, es geht rucklig und ist ungewohnt, aber spaeter dann kein Problem mehr und es geht ohne viel Nachdenken

    Fuer mich stellen Pointer auf jeden Fall kein Problem mehr dar. Bin aber auch schon laenger dabei. Wie gesagt, gewoehnungssache.

    Mfg,

    Kolazomai
     
  16. 14. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    mhhh bis jetzt hat sich der nutzen für mich noch nicht so rausgestellt. einzige praktische ist halt das man in funktionen variablen direkt verändern kann
    den rest hab ich wohl noch nicht so ganz verstanden ^^
     
  17. 14. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    Ein ganz simples Beispiel wurde doch schon genannt.

    Ein sich vergrößerndes Array wäre ein Beispiel.
     
  18. 14. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    Das ganze ist halt einfach sehr praktisch, weil sie ja einfch nur auf einen Speicherbereich zeigen. Dass kann man wunderbar ausnutzen, wenn man z.B. Netwerkprogrammierung betreibt.

    Dann kann man sich das Protokoll (ich nehm als bsp. mal die SOCKS5 Cmd Anfrage) als struct erstellen...
    ..so dass die Werte sehr einfach befüllbar sind:
    Verschicken muss man das ganze ja aber als Kette von Bytes und genau hier zahlen sich die Pointer aus. Denn ein struct legt die einzelnen Variablen hintereinander im Speicher ab. Jetzt erstellt man sich einen Pointer...
    ...und castet ihn, so dass er auf die Anfangsaddresse von dem struct zeigt:
    Jetzt kann man mit ptr[0] z.B. auf das erste Byte zugreifen.


    Mir ist jetzt beim Schreiben aufgefallen, dass du vieles davon wahrscheinlich nicht verstehst, aber sieh es einfach als Beispiel an, wie man Pointer sinvoll benutzen kann
     
  19. 14. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    Okay, das mit dem Socks5-Struct is wirklich sehr hoch gegriffen. Meiner Meinung nach ist der Weg über den Pointer auch etwas umständlich. Normalerweiße würde man sowas über eine Union lösen:
    Code:
    union S5CMD {
     struct {
    u_char version;
    u_char cmd;
    u_char rsvd;
    u_char addr_type;
    u_long dst_addr;
    u_short dst_port;
    } conn;
     unsigned char bytes[10];
    };
    conn hat 10 bytes, genauso wie das char-array am ende. Und union bedeutet ja, das alle Elemente auf dem gleichen Speicherplatz liegen. D.h. man kann conn einfach über die Feldvariablen befüllen und dann mit bytes auf den Speicherplatz zugreifen.

    Ein weiteres Beispiel wäre z.B. ein Pointer auf ein Objekt, was an mehren anderen Orten gebraucht wird. Wenn du z.B. ein Objekt A hast, was an mehreren "Orten", z.B. in mehreren Klassen/Structs gebraucht wird, dann kannst du in den structs einfach einen Pointer setzen. Das ist zum einen eine Platzersparnis (Ein Pointer braucht nur 4 bytes, jedesmal ein eigenes Objekt kann unter Umständen viel mehr Platz benötigen), zum anderen werden Änderungen an A in allen Objekten die auf A verweisen übernommen. Wenn du da keine Pointer nimmst, müsstest du jedesmal jedes A updaten.
     
  20. 15. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    solangsam ergibt sich ein sinn ^^

    jetzt noch mal ne frage, die beim lesen des galileo computing ebooks entstanden ist:

    Code:
    int *ptr;
    int var, var2;
    
    // Initialisieren: ptr bekommt die Adresse von var.
    ptr =& var;
    
    // Dereferenzierung : var bekommt den Wert 100 zugewiesen.
    *ptr=100;
    
    
    // var2 mit demselben Wert wie var initialisieren
    var2 = *ptr;
    
    *ptr+=100; // Dereferenzierung: var wird um 100 erhöht.
    (*ptr)++; // Dereferenzierung: var hat jetzt den Wert 201.
    (*ptr)--; // var hat wieder den Wert 200.
    ptr=&var2; // ptr zeigt auf var2.
    
    printf("%d", *ptr); // Gibt Wert von var2 aus.
    printf("%p", &ptr); // Gibt Adresse von ptr aus.
    printf("%p", ptr); // Gibt Adresse von var2 aus.
    wann schreibe ich denn jetzt *ptr, wann &ptr und wann nur ptr?

    *ptr nehme ich an wenn ich den wert haben will, auf den der zeiger zeit... und die anderen beiden? wo ist da der unterschied und warum kann man 2 verschiedene adressen wiedergeben?
     
  21. 15. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    Mit *ptr hast du recht, das zeigt auf den Wert, den es dereferenziert.

    ptr gibt die Adresse an, die var hat. Schließlich weißt du sie ja mit ptr =& var; zu.

    &ptr hingegen gibt die Adresse an, die ptr selber hat, denn auch der Pointer muss irgendwo im Speicher abgelegt werden.
     
  22. 16. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    okay das macht sinn (so mehr minder^^)

    jetzt aber schonwieder ne frage dazu:
    Code:
    #define PI 3.141592f
    
    void kreisflaeche(float *wert) {
     *wert = ( (*wert) * (*wert) * PI );
    }
    
    int main(void) {
     float radius;
    
     printf("Berechnung einer Kreisfläche!!\n\n");
     printf("Bitte den Radius eingeben : ");
     scanf("%f", &radius);
     /* Adresse von radius als Argument an kreisflaeche() */
     kreisflaeche(&radius);
     printf("\nDie Kreisfläche beträgt : %f\n", radius);
     return EXIT_SUCCESS;
    }
    warum gebe ich &radius an die funktion, integriere das dann aber mit *wert ? warum übergebe ich die adresse mit "&radius" und nicht mit "radius"? wenn ich vorher einen pointer initialisieren würde und den dann in die funktion übergebe, würde ich dann "%pointername" oder "pointername" schreiben?

    sry das der thread so lang wird aber es will einfach nicht in den kopf
     
  23. 16. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    Das & spricht die Adresse an, wo du Variable im Speicher liegt.

    An dem * erkennt man, dass es sich nicht um eine normale Variable handelt, sondern eben um Zeiger, in denen man eine Adresse speichern kann.

    Normal übergibt man immer die Adressen der Variablen. Macht ja auch irgendwie Sinn, wozu dann Pointer verwenden. Sonst kannst ja gleich ohne Adressen arbeiten.

    Oder hab ich dich falsch verstanden?
     
  24. 16. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    Hoi,

    du verwechselt da einige Sachen
    Wenn du so eine Angabe hast:
    Code:
    int *ptr;
    Dann ist das einfach ein Zeiger, der auf einen int zeigt. Wenn das in einer funktion als Argument steht:
    Code:
    void foo(int *ptr);
    Dann erwartet die Funktion einen Zeiger (also eine Addresse) auf einen Integer.

    Mit dem &-Operator gibst du die Addresse einer Variable zurück. z.B.:
    Code:
    int a = 1;
    int *ptr = &a; // ptr zeigt jetzt auf die [B]addresse[/B] von a;
    
    printf("a = %d\n", a);
    printf("*ptr = a = %d\n", *ptr);
    printf("ptr = %p\n", ptr);
    Es ist also gar nicht so schwer, du darfst nur nicht & und * verwechseln. Zur Funktion kreisflaeche:
    Die erwartet einen Zeiger auf einen int. In der Berechnung kann aber natürlich nicht mit der Adresse multipliziert werden, sondern mit dem Wert, der an der Addresse gespeichert ist. Deswegen wird *wert verwendet.
    Normalerweiße würde man den Radius als normale Variable, nicht als Zeiger übergeben, aber da es im Kapitel wohl um Zeiger geht, wurde halt ein Pointer verwendet.
     
  25. 16. November 2009
    AW: Ich verzweifle an Pointern...(malloc etc.)

    jetz muss ich nochmal reinquatschen ^^

    man verwendet also "&" wenn man an die adresse von einer variablen und "*" wenn man an die adresse will auf die ein pointer zeigt.

    Code:
    int *foo = 1; //wobei ich mir ned sicher bin ob das so funktioniert, 1 wäre ja konstant
    int bar = 2;
    
    mach_was(*foo); //übergibt adresse auf die der pointer zeigt
    mach_was(&bar); //übergibt die adresse der variablen
    
    //und im grunde müsste das hier auch funktionieren:
    int *baz = &bar; //baz zeigt auf bar
    ganz blöd gefragt: eine adresse ist ja nur eine zahl, würde sowas funktionieren:
    Code:
    int addr = 0x1234abcd;
    //ich geh davon aus, dass mir bekannt ist welcher typ da liegt
    int *pntr = addr; //zeigt jetzt auf eine variable mit der adresse 0x1234abcd
     
  26. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.