Speicherverwaltung

Dieses Thema im Forum "C/C++" wurde erstellt von rdg, 19.09.2007.

  1. rdg

    rdg ???

    Dabei seit:
    12.10.2006
    Beiträge:
    357
    Zustimmungen:
    0
    Ort:
    Berlin
    Hi,

    ich brauche mal Eure hilfe. Ich habe folgendes:

    int *pnZahlen=new int[nAnzahl];

    So, ist das nun ein Zeiger? Wenn ja, warum lassen sich dann Werte einfügen?

    for(int i=0; i<nAnzahl; i++){
    pnZahlen = i;
    cout<<"pnZahlen["<<i<<"]: "<<pnZahlen<<endl;
    }


    Eigentlich dürften doch nur Adressen auf welche das entspr. Feld zeigt gespeichert werden, oder?
    Wenn nein, warum gibt es dann überhaupt Zeiger, ich meine Adressen könnte ich doch auch in normale Variablen einfügen.

    gruß rdg
     
  2. Anzeige

    Schau dir mal diese Kategorie an. Dort findest du bestimmt etwas.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  3. #2 Mµ*e^13.5_?¿, 19.09.2007
    Mµ*e^13.5_?¿

    Mµ*e^13.5_?¿ Routinier

    Dabei seit:
    21.02.2006
    Beiträge:
    453
    Zustimmungen:
    0
    Weil ein Zeiger und ein Array so ziemlich aufs gleiche hinauskommt in C und C++.

    Du hast einen Zeiger auf einen Array, kein Array von Zeigern.
     
  4. rdg

    rdg ???

    Dabei seit:
    12.10.2006
    Beiträge:
    357
    Zustimmungen:
    0
    Ort:
    Berlin
    erstmal wirklich vielen Dank Dir für deine Antwort !!!

    Warum kommt ein Zeiger auf's gleiche hinaus wie ein Array?

    Wie heißt das Array auf das der Zeiger pnZahlen zeigt?
     
  5. #4 Mµ*e^13.5_?¿, 19.09.2007
    Mµ*e^13.5_?¿

    Mµ*e^13.5_?¿ Routinier

    Dabei seit:
    21.02.2006
    Beiträge:
    453
    Zustimmungen:
    0
    Ein Array ist ein Zeiger auf den ersten Wert einer Reihe von Werten.

    Dein Zeiger pnZahlen ist also folglich dein Array.


    Vielleicht macht es dieses bisschen Code den Zusammenhang zwischen Pointer und Array deutlicher.
    Code:
    int ary[3];
    *ary = 5;
    ary[1] = 6;
    *(ary + 2) = 7;
    for (int i = 0; i < 3; i++)
    	cout << "ary[" << i << "]: " << ary[i] << endl;
     
  6. Lesco

    Lesco segmentation fault

    Dabei seit:
    18.12.2005
    Beiträge:
    67
    Zustimmungen:
    0
    Ort:
    Hessen
    Die Deklarationen:
    Code:
    int foo[n];
    /*und*/
    int *bar = new int[n];
    
    laufen auf das selbe hinaus, mit dem Unterschied, dass der Speicher sich beim ersten Fall auf dem Stack, beim zweiten auf dem Heap befindet. Bei der Variable foo handelt es sich intern auch nur um einen Zeiger auf den Beginn des Feldes, nicht um das eigentliche Array.(Lässt sich auch durch printf("%p\n",foo) gut sehen)
    Durch den []-Operator erfolgt dann die Dereferenzierung dieses Zeigers. Dadurch sind auch folgende Zugriffe gleich:
    Code:
    var = foo[0];
    var = *foo;
    /*oder*/
    var2 = foo[2];
    var2 = *(foo+2); 
    
    Edit: Zu langsam..
     
  7. rdg

    rdg ???

    Dabei seit:
    12.10.2006
    Beiträge:
    357
    Zustimmungen:
    0
    Ort:
    Berlin
    Also:
    int foo[1]:
    foo [0] = 100;
    foo [1] = 200;

    foo = Adresse im Speicher
    foo[0] 100
    foo[1] 200

    *foo ware foo, also adresse von foo
    oder ?
     
  8. Lesco

    Lesco segmentation fault

    Dabei seit:
    18.12.2005
    Beiträge:
    67
    Zustimmungen:
    0
    Ort:
    Hessen
    Erstmal müsste es int foo[2] heißen, da du 2 Elemente darin speicherst.
    Mit dem Ausdruck "*foo" würdest du auf das erste Element des Feldes zugreifen, also foo[0].
     
  9. rdg

    rdg ???

    Dabei seit:
    12.10.2006
    Beiträge:
    357
    Zustimmungen:
    0
    Ort:
    Berlin
    Gut, also ist ein Zeiger lediglich ein Array, welcher auf die erste Stelle zeigt.

    Doch dann bleibt Frage wozu gibt es Zeiger?

    Tut mir wirklich leid, wenn ich so blöde frage, doch ich versteh es wirklich nicht ganz.
     
  10. #9 SkydiverBS, 20.09.2007
    Zuletzt bearbeitet: 20.09.2007
    SkydiverBS

    SkydiverBS Tripel-As

    Dabei seit:
    15.01.2005
    Beiträge:
    207
    Zustimmungen:
    0
    Ort:
    Freising
    Genau andersherum: Der Name des Arrays kann als Zeiger betrachtet werden, welcher auf die Adresse des ersten Array-Elements im Speicher zeigt.

    Wichtig: Zwischen Zeiger und Array gibt es zwar einen großen Zusammenhang, sie sind aber nicht absolut gleichbedeutend. Ein Zeiger ist eine Variable dessen Wert man beliebig ändern (z.B. inkrementieren) kann. Bei einem Array geht das nicht. Der Arrayname verweist immer auf die gleiche Adresse im Speicher, die dem Array bei der Deklaration zugewiesen wurde.

    Beispiel:
    Code:
    // arr zeigt auf Adresse des ersten Elements (10)
    int arr[3] = {10, 20, 30};
    // ptr zeigt auf Adresse des ersten Elements (10)
    int *ptr = arr;
    
    // ptr zeigt auf Adresse des zweiten Elements (20)
    ptr++;
    // Ungültige Operation (führt zu Compiler-Fehler)
    arr++;
    
    Ich empfehle dir die Lektüre des Wikipedia-Artikels zu Zeigern und des entsprechendem Kapitels in dem online verfügbaren Buch C von A bis Z.

    Wenn du dann noch ungeklärte Fragen hast kannst du dich ja nochmal melden.

    Gruß,
    Philip
     
  11. #10 tr0nix, 20.09.2007
    Zuletzt bearbeitet: 20.09.2007
    tr0nix

    tr0nix der-mit-dem-tux-tanzt

    Dabei seit:
    11.07.2003
    Beiträge:
    1.585
    Zustimmungen:
    0
    Ort:
    Schweiz, Opfikon/Glattbrugg
    Ich habe gerade Zeit und Geduld :). Ein Beispiel wozu du Zeiger brauchst, ist das dynamische alloziieren von Speicher.

    Angenommen du schreibst ein Programm, welches Zahlen einliest. Wieviele Zahlen das Programm einliest ist nicht gegeben. Hier kannst du nicht einfach sagen ich alloziiere mal int[X] vor weil du entweder mehr Zahlen einlesen könntest als du alloziiert hast, oder du viel zu viele Zahlen allozierst die du gar nicht brauchst -> Memoryverschwendung.

    Ein Beispiel wie sich das lösen lässt, wäre mit einer einfach verketteten Liste. Eine solche wird beispielsweise in einem Struct oder mittels einer Klasse implementiert (hier als struct):
    Code:
    struct zahlenreihe {
    zahlenreihe *next;
    int zahl;
    }
    Wie du siehst, referenziert ein Pointer *next auf denselben Datentyp. Der Sinn davon ist, dass du bei einem Element anfängst einzulesen und - wenn du ein weiteres brauchst - mittels dem *next Pointer ein weiteres Element alloziierst (ein Pointer selbst alloziiert ja keinen Datentyp, er verweist nur darauf). Wenn du nochmals ein Element brauchst, hast du ja wieder einen *next Pointer den du zum alloziieren verwenden kannst. Wenn du beim letzten Element bist und *next nicht mehr brauchst, setzt du diesen auf NULL. Wenn du nun die Liste durchsuchen möchtest, fängst du beim ersten Element an und gehst die Liste durch, bis *next == NULL ist.

    Pseudocode:
    Code:
    int zahl = 0;
    zahlenreihe meineZahlen;
    zahlenreihe *aktuellesElement = &meineZahlen;
    
    solange(wahr) {
     cout << "Bitte Zahl eingeben, bei -1 wird abgebrochen" << endl;
     zahl = zahlEinlesen();
     if(zahl == -1) break;
    
     aktuellesElement->zahl = zahl;
     aktuellesElement->next = new zahlenReihe;
     aktuellesElement = aktuellesElement->next;
     aktuellesElement->next = NULL;
    }
    
    cout << "Die eingegebenen Zahlen sind:" << endl;
    aktuellesElement = &meineZahlen;
    solange(wahr) {
     cout << aktuellesElement->zahl << endl;
     if(aktuellesElement->next != NULL) { aktuellesElement = aktuellesElement->next; } else { break }
    }
    
    Bin mir gerade nicht sicher wegen den * und &, aber ich denke ist korrekt so. Lasse mich gerne korrigieren :).

    Anmerkungen:
    - es muss mind. 1 Eintrag gemacht werden, ich habs KIS mässig implementiert um zu erklären
    - ja, wenn man C++ programmiert sollte man nur noch Klassen bzw. Objekte verwenden und keine Structs, ich weiss :)
     
  12. #11 Lesco, 20.09.2007
    Zuletzt bearbeitet: 20.09.2007
    Lesco

    Lesco segmentation fault

    Dabei seit:
    18.12.2005
    Beiträge:
    67
    Zustimmungen:
    0
    Ort:
    Hessen
    Das '*' ist fehl am Platz, wenn du den "->"-Operator verwendest, da dieser bereits die Dereferenzierung übernimmt:
    Code:
    /*Falsch:*/
    *aktuellesElement->zahl = zahl;
    /*Richtig:*/
    aktuellesElement->zahl = zahl;
    /*oder auch:*/
    (*aktuellesElement).zahl = zahl;
    
     
  13. #12 tr0nix, 20.09.2007
    Zuletzt bearbeitet: 20.09.2007
    tr0nix

    tr0nix der-mit-dem-tux-tanzt

    Dabei seit:
    11.07.2003
    Beiträge:
    1.585
    Zustimmungen:
    0
    Ort:
    Schweiz, Opfikon/Glattbrugg
    Ah stimmt, ich falle auf das immer wieder rein.. thx für die Erklärung. Ich korrigiers gleich mal.

    @rdg:
    Wie gehabt alloziiert ein Zeiger selbst kein Memory.
    Wenn du dies aber mit new kombinierst, gibt "new" einen Addressbereich zurueck wo die allozierten Datenbereiche liegen. Der Pointer erhält durch die Zuweisung (=) diese Addresse und du kannst dort Daten ablegen und abrufen:
    Wichtig ist, dass du deinen Zeiger nicht verlierst. Sprich am besten machst du immer einen Zeiger, welcher auf den Startbereich zeigt und einen weiteren Zeiger, mit welchem du die Daten mutierst bzw. abrufst.
     
  14. rdg

    rdg ???

    Dabei seit:
    12.10.2006
    Beiträge:
    357
    Zustimmungen:
    0
    Ort:
    Berlin
    So, erstmal wirklich vielen dank für die Hilfe!!!

    @tr0nix
    1. aktuellesElement = aktuellesElement->next;
    2. aktuellesElement->next = NULL;
    <- hier komm ich leider noch ein wenig durcheinander,
    1. hiermit Speichere ich die Adresse von zahlenreihe.next in den Zeiger aktuellesElement
    2. das darauf folgende struct wird auf NULL gesetzt
    oder, ist das so richtig.

    Habe wirklich bevor ich euch fragte in Bücher geschaut, doch nirgends eine befiedigende Antwort erhalten:
    DATA BECKER->Grundlagen Buch:
    ... unären Verweis- oder Indirektionsoperator <- sorry, doch nichts klar
    Galileo->c++ für c:
    präsentiert Adresse und Typ einer Variablen <-Ja schon klar doch warum Startfrage?

    Die Bücher die SkydiverBS mir empfohlen hat, werde ich mir gleich mal anschauen

    und wirklich vielen Dank!!!
     
  15. Anzeige

    Vielleicht findest du HIER Antworten.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  16. tr0nix

    tr0nix der-mit-dem-tux-tanzt

    Dabei seit:
    11.07.2003
    Beiträge:
    1.585
    Zustimmungen:
    0
    Ort:
    Schweiz, Opfikon/Glattbrugg
    aktuellesElement ist ein Pointer auf ein zahlenreihe - Struct. In diesem Struct habe ich wiederrum einen Pointer, der auf die nächste Zahl verweist (*next).

    Wenn ich jetzt sage, dass die Addresse von aktuellesElement auf die Addresse von aktuellesElement->next gesetzt wird, dann gehe ich einfach einen Schritt weiter zur nächsten Zahl. Da ich ja noch nicht weiss, ob diese Zahl nun die letzte sein wird, setze ich explizit aktuellesElement->next auf NULL um es vorerst als letztes Element zu kennzeichnen (ansonsten zeigt der Pointer irgendwohin ins Memory und du kannst Segfaults erzeugen wenn du darin zu arbeiten versuchst).
     
  17. #15 rdg, 20.09.2007
    Zuletzt bearbeitet: 20.09.2007
    rdg

    rdg ???

    Dabei seit:
    12.10.2006
    Beiträge:
    357
    Zustimmungen:
    0
    Ort:
    Berlin
    So,
    hab mich weiter mit dem Problem befaßt, dabei ist mir aufgefallen:
    Hoffe es bleibt übersichtlich:
    1.
    Warum:
    int ary[2] = {100,101};
    ary: 0xbfebce74 &: 0xbfebce74
    ary[0]: 100 &: 0xbfebce74
    ary[1]: 101 &: 0xbfebce78
    -> wenn in ary im inhalt seine eigene Adresse steht,
    wie kann dann bei ary[0] mit der Adresse von ary im inhalt 100 stehen?

    2.
    Bei Zeigerarray, warum:
    *zeig[0]=100:
    zeig[0]| &: 0xbff216cc inhalt: 0xbff216c8

    ???
     
Thema:

Speicherverwaltung

Die Seite wird geladen...

Speicherverwaltung - Ähnliche Themen

  1. Tomcat Speicherverwaltung

    Tomcat Speicherverwaltung: Hi Zusammen, ich habe mir von Apache die Tomcat binaries geladen und mittels selbergebautem StartScript laufen lassen. Ansich funktioniert...
  2. Speicherverwaltung AIX

    Speicherverwaltung AIX: Grüsse brauche ein wenig Hilfe bei Vorplanung für Speicher Bedarf auf einer aix Kiste. aktuell zeigt nmon FileSystemCache 9.4% Free...
  3. Festplattenspeicherverwaltung

    Festplattenspeicherverwaltung: Hallo, folgendes, mir unerklärliches Problem. ich habe viel mit Kaudiocrator und Grip herumexperimentiert, bis ich mit dem Ergebnis zufrieden...