kostenloser Webspace werbefrei: lima-city


[c++] Zeiger

lima-cityForumProgrammiersprachenC/C++ und D

  1. Autor dieses Themas

    cursed

    cursed hat kostenlosen Webspace.

    Hallo Leute,

    wollte mal fragen, wie ihr vorgegangen seit, als ihr "Zeiger" gelernt habt ...
    ich versuchs zu begreifen, aber irgendwie verwirrt mich das ganze immer wieder aufs neue ...

    mfg
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. f*********s

    vergiss zeiger..und lern weiter...

    der clou ist:

    ich habe fr?her zeiger verwendet ohne es zu wissen
    erst als ich c++ noch mal intensiver gemacht habe,
    merkte ich was zeiger sind...lies es dir durch, schau
    die beispiele an und geh weiter...irgendwann isses alles
    genau wie das andere zeuch


    mfg
  4. Autor dieses Themas

    cursed

    cursed hat kostenlosen Webspace.

    will aber net weitergehn bevor ich das nicht kann *gg* bitte um weitere antworten ...

    vielleicht hat ja wer ein paar ?bungsbeispiele die mir vielleicht einen Einblick geben k?nnen ...

    mfg
  5. t*****b

    Is ja lang her als ich mit C/C++ gearbeitet habe, aber sind Zeiger/Pointer/Chars net die Dinger wo auf eine Speicheradresse verweisen?? Hatte ich am Anfang au net gepeilt, is aber net so schwer, einfach mal en bissle nach Tutorials googeln.
  6. Autor dieses Themas

    cursed

    cursed hat kostenlosen Webspace.

    ich glaub das peilen ziemlich viele am anfang net *gg* hab ich schon des ?fteren geh?rt .... ^^

    najo, ich werd mich mal umschaun ... vielleicht hat aber trotzdem noch jemand ein paar tipps bzw. erfahrungen mit Zeigern, die er hier schildern w?rde :)

    mfg
  7. Also wir nehmen das Zeug bei der Ausbildung zum IT Assistenten durch... unser Lehrer hat das irgendwie total versaut und wir haben leider da eine misserable note bekommn. Da ich aber denke das unsere abschlusspr?fung sich nochmals mit dem thema besch?ftigen wird und ich deshalb darauf angewiesen bin... ?hhmmm...

    noch irgendwelche tipps zum thema Zeiger?
    Welche B?cher w?rde ihr empfehlen und vielleicht fast noch wichtiger, welche B?cher w?rdet ihr nicht zum lernen f?r "Einsteiger" empfehlen????

    Ich hab die erfahrung gemacht, das es in manchen b?chern ziemlich crashkurs m?ssig erkl?rt wird oder aber auch so kompliziert erkl?rt wird, das da nahe zu niemand mehr durch blickt =(

    PS: Helft wenn ihr k?nnt, aber bitte nicht solche antworten wie "?berspring das Thema einfach" -> das lassen die Lehrer und Ausbilder glaub ich nich gelten =/
  8. l******c

    also ich weis nicht was zeiger sind oder sonst was habe auch keine ahnung von c oder c++ oder etwas in die richtung aber ich kann euch sagen b?cher Markt+Technik (Homepage: http://www.mut.de) aus der easy reihe sind recht einfach zu kapieren hin gegen kann ich die ie b?cher von "f?r dummies" (ich weis nicht ob die Firma so hei?t aber es steht auf den b?chern drauf) nicht empfehlen damit hatte ich extreme probs denn da waren keine quelltext beispiele gegeben. vlt. lag es daran das es ?ber vb war aber ich denke die sindgenerel schwerer also lieber von markt+ technik


    EDIT 0-checka:
    Eigentlich soll man ja nichts sagen, wenn man keine Ahnung hat ;-)
    Ich lasse den Beitrag hier mal trotzdem stehen, da ich der selben Meinung bin. Generell kann man von den "... f?r Dummies" B?chern nur abraten.

    Beitrag ge?ndert am Thu, 06.01.2005 18:45 von 0-checka
  9. 0******a

    Ich habe bisher noch kein einziges Buch gelesen, in dem Zeiger wirklich gut erkl?rt sind (und ich habe viele B?cher gehabt, teilweise auch, um die zu rezensieren). Daher hier mal eine ausf?hrliche Erkl?rung von mir. Zu der Frage, wie man das am besten lernt, kann ich nur sagen: Learning by doing. Man muss Aufgabenstellungen finden/bekommen, bei denen man dazu gezwungen ist, Zeiger zu benutzen. Anders lernt man das nur sehr m?hsam. Das gute bei Zeigern ist allerdings: Es ist wie Fahrrad fahren, wenn man es einmal gelernt hat, wird man nie wieder vergessen, wie es geht. Aber auch Fahrrad fahren kann man nur mit Praxis lernen, Theorie ist da einfach fehl am Platz.


    Zeiger sind f?r drei Dinge gut:
    1. Verwendung von dynamischen Speicher
    2. Bearbeiten von Arrays
    3. ?bergabe von Variablen/Funktionen/Objekten an andere Programmteile


    Da die ersten beiden ziemlich ?hnlich sind, werde ich das Benutzen von Zeigern am Beispiel des Schwierigeren (Dynamischer Speicher) erkl?ren.




    Zeiger auf statischen Speicher (Variablen):

    Angenommen, wir haben diesen Beispielcode:
    int i = 5;
    int * p = &i; // p zeigt jetzt auf i

    /* 1.: */ cout << "i: " << i << "\n";
    /* 2.: */ cout << "p: " << p << "\n"
    /* 3.: */ cout << "&p: " << &p << "\n";
    /* 4.: */ cout << "*p: " << *p;

    Bei der Ausgabe wird im 1. Fall nat?rlich "5" ausgegeben.
    Im 2. Fall wird der Inhalt von p ausgegeben und das ist die Adresse von i im Speicher, da p ja auf i zeigt.
    Im 3. Fall wird die Adresse von p selber angezeigt, also wo p im Speicher liegt.
    Im 4. Fall wird der Inhalt von dem angezeigt, auf das p zeigt, also der Inhalt von i, ergo "5".

    Graphisch dargestellt sieht das ganze ungef?hr so aus:

    &nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i
    &nbsp;&nbsp;&nbsp;&nbsp;96&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 97&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;98&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;99&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;101
    ----------------------------------------------------
    &nbsp;&nbsp;&nbsp;100&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|
    ----------------------------------------------------

    In der ersten Zeile steht, um welche Variable es sich handelt.
    In der zweiten Zeile steht die Speicheradresse.
    Die K?stchen in den n?chsten Zeilen sollen die eigentlichen Stellen im Speicher sein (der Einfachheit halber ist ein int jetzt nur ein Byte breit).
    Was in den K?stchen selbst drin steht, ist das, was im Speicher abgelegt ist.
    Bei der vorhin im Beispielcode geschriebenen Ausgabe wird also folgendes rauskommen:
    5
    100
    96
    5





    Zeiger auf statischen Speicher (Arrays):

    Ein gutes Beispiel f?r Arrays sind Strings.
    Beispielcode:

    char bla[] = "Hallo";
    char * p;


    Bei Arrays ist zu beachten, das sie auch faktisch Zeiger sind (n?heres dazu im Thread http://www.lima-city.de/boards?m=thread&id=14204). Wie lasse ich den Zeiger jetzt auf das Array zeigen? Einfach mit:
    p = bla;
    Hier wird kein Adressoperator gebraucht, weil man einem Zeiger einen anderen zuweist.
    Und wie lasse ich p auf das zweite Zeichen im Array zeigen?
    p = &bla[1];
    Das zweite Zeichen im Array ist bla[1], allerdings ist das dann kein Zeiger, sondern nur ein Element des Arrays. Daher m?ssen wir an dieser Stelle wieder den Adressoperator benutzen.
    Ich habe gesehen, das man Zeigern einfach den Inkrementoperator (also ++) benutzt, was soll das und wie funktioniert das?
    Angenommen, p zeigt auf bla und wir wollen nun, das p auf das n?chste Element im Array zeigt, dann schreiben wir einfach:
    p++;
    Das geht, weil durch p++ der Wert um 1 inkrementiert wird und daher auf die n?chste Stelle im Speicher passiert. Da Arrays immer als ganze St?cke im Speicher angelegt werden, kann man den Zeiger einfach manipulieren. Das selbe gilt nat?rlich analog f?r die anderen Operatoren wie zum Beispiel --, + oder -. Nur Multiplikations-, Divisions-, und Modulooperator sowie die bin?ren Operatoren machen im Bezug auf Zeiger keinen Sinn. Es muss nur beachtet werden, das man nicht ?ber die Arraygrenzen hinausgeht (weder nach oben, noch nach unten).
    Noch eine Anmerkung wegen der Aussage "Arrays [werden] immer als ganze St?cke im Speicher angelegt". Das stimmt so nat?rlich nicht. Wo und wie im Speicher das Betriebssystem statischen Speicher ablegt oder ob die Sachen vielleicht sogar in eine Auslagerungsdatei geschrieben werden, wissen wir als Programmierer in dem Moment bei modernen Betriebssystemen nicht (bei DOS z.B. war das wirklich dort, wo man was hingeschrieben hat). Das Betriebssystem k?mmert sich darum, das Arrays im Speicher f?r uns als ein St?ck erscheinen. Daher stimmt die Aussage eigentlich, uneigentlich aber nicht (ich hoffe, ihr seid jetzt richtig verwirrt :biggrin:).



    Zeiger auf dynamischen Speicher (Variablen):
    Hier kommen zwei neue Dinge ins Spiel:
    1. Die Operatoren new und delete bzw. deren C ?quivalente als Funktionen
    2. Das Problem von Speicherlecks

    Dynamischer Speicher wird dann gebraucht, wenn man als Programmierer nicht bestimmen kann, wieviel Speicherplatz (wie viele Variablen) zur Laufzeit ben?tigt werden. In ISO C++ gibt es zwei Operatoren, die sich darum k?mmern, Speicher vom Betriebssystem zur Laufzeit anzufordern und auch wieder freizugeben. Zum Anfordern benutzt man "new", zum Freigeben "delete". In ANSI C gibt es die ?quvialente malloc(), calloc() und realloc() zum Anfordern von Speicher und free() zum Freigeben.
    Beispiel zur Verwendung von new und delete:
    char * p;
    p = new char;
    [...irgendwas mit p machen, bis es nicht mehr gebraucht wird]
    delete p;


    p kann nach dem Anfordern von Speicher analog zu Zeigern auf statischen Speicher benutzt werden; es gibt da keine Unterschiede.

    Was sind Speicherlecks?
    Fordert man mit new Speicher an, so kann der dynamisch reservierte Speicher nur ?ber den Zeiger angesprochen werden, der von delete zur?ckgegeben wird. Wird die Zeigervariable w?hrend der Laufzeit des Programms ung?ltig, kann man weder auf den reservierten Speicher zugreifen, noch ihn l?schen.
    Beispiel:
    void blubb(void)
    {
    &nbsp;&nbsp;&nbsp;char * p;
    &nbsp;&nbsp;&nbsp;p = new char;
    &nbsp;&nbsp;&nbsp;// ...irgendwas mit p machen, bis es nicht mehr gebraucht wird
    }

    In diesem Fall wird kein "delete p" gemacht. Jedes Mal, wenn in dem Programm die Funktion blubb aufgerufen wird, geht ein Byte "verloren", da p ausserhalb der Funktion nicht mehr g?ltig ist, kann weder darauf zugegriffen werden, noch kann der Speicher gel?scht werden. Irgendwann steht dem System kein Speicher mehr zur Verf?gung und st?rzt m?glicherweise ab.

    Weiteres zu new:
    Der R?ckgabewert von new wurde nicht ?berpr?ft. Es kann sein, dass das System den angeforderten Speicher nicht zur Verf?gung stellen kann (einzig realistischer Grund daf?r ist, das zuwenig Speicher vorhanden ist). In diesem Fall liefert new NULL zur?ck. Also sollte man beim Anfordern von Speicher den R?ckgabewert ?berpr?fen:
    char * p;
    p = new char;
    if (p == NULL) // Fehlermeldung oder sonstwas machen


    Mit new kann man nat?rlich auch Speicher f?r andere Variablentypen als nur char anfordern. Dazu einfach statt "char" einen Variablentypen benutzen und p als richtigen Typen definieren. Aber auch das benutzen von Strukturen (struct) oder Klassen ist m?glich. Hat man zum Beispiel eine Klasse "Hund" und will die dynamisch erzeugen, geht das so:
    Hund * p;
    p = new Hund;



    Die R?ckgabewerte von new kann man ohne Probleme per Typecast auf alle anderen Zeigertypen benutzen, da Zeiger immer gleich gross sind.


    Weiteres zu delete:
    delete darf nur auf Zeiger angewendet werden, die auf noch g?ltigen mit new reservierten Speicher zeigen. Die einzige Ausnahme ist, wenn Zeiger auf NULL (sozusagen nirgendwohin) zeigen. Wird delete auf etwas anderes angewendet, ist das Verhalten undefiniert (meist st?rzt das Programm einfach ab, kommt allerdings auf den Compiler und das Betriebssystem an).
    Beispiele:

    char * p = new char;
    delete char;
    delete char;

    delete wurde zwei Mal auf die gleiche Variable bzw. auf den selben reservierten Speicher angewendet. Absolut verboten.

    char * p;
    delete p;

    delete wurde auf nicht reservierten Speicher angewendet. Total verboten.
    Um solche Fehler zu verhindern, sollten Zeiger, die sp?ter auf dynamisch reservierten Speicher zeigen sollen, bei der Definition mit NULL initialisiert werden. Auch nach einem delete sollten die Zeiger auf NULL gesetzt werden. Beispiel:
    char * p = NULL;
    delete p; // 1. delete
    p = new char;
    //[... irgendwas wird mit p gemacht]
    delete p; // 2. delete
    p = NULL;
    delete p; // 3. delete

    Nur das 2. delete ist richtig. Da bei dem 1. und 3. delete p vorher auf NULL gesetzt wurde, k?nnen sie nichts schlimmes ausrichten, es gibt also kein Programmabsturz oder ?hnliches.




    Zeiger auf dynamischen Speicher (Arrays):
    Im vorherigen Teil wurde gezeigt, wie auf einzelne Variablen im dynamischen Speicher zugegriffen, beziehungsweise wie dieser Speicher angefordert und wieder freigegeben wird. Das Erstellen von einzelnen Variablen auf dem dynamischen Speicher macht eigentlich keinen Sinn (nur bei Klassen ergibt das einen Sinn), ausser man verwendet verkettete Listen. (Anmerkung: Verkettete Listen zur verwenden macht nie einen Sinn, da durch den sequentiellen Zugriff auf die Daten die Laufzeit betr?chtlich erh?ht wird) Eigentlich erstellt man sich fast immer per new ein Array von Variablen, das so gross ist, wie gerade ben?tigt.
    Als Beispiel daf?r ein Programm, das eine beliebige Anzahl an Werten einliest und den Durchschnittswert berechnet. Die Anzahl wird vom Benutzer w?hrend der Laufzeit des Programmes eingegeben (teilweise Pseudocode):
    unsigned int iAnzahl;
    float * pDaten = NULL;
    Anzahl gew?nschter Datenmenge einlesen und iAnzahl zuweisen;
    pDaten = new float[iAnzahl];
    for (unsigned int i = 0; i < iAnzahl; i++)
    {
    &nbsp;&nbsp;&nbsp;pDaten = Wert einlesen;
    }
    Durchschnitt berechnen;
    delete [] pDaten;

    Neu ist hier eigentlich nur, wie Arrays erstellt werden mit new:
    new Typ[Anzahl];
    und wie der Speicher wieder freigegeben wird:
    delete [] Arrayzeiger;
    Bei delete auf Arrays m?ssen die eckigen Klammern normalerweise benutzt werden, da sonst nur Speicher f?r ein Element des Arrays freigegeben wird. Allerdings sind die meisten Compiler da nicht so nachtragend und l?schen gleich den Speicher f?r das ganze Array.




    Ich habe leider keine Zeit mehr, werde den Rest in n?chster Zeit aber noch erg?nzen. Daher hier nur die ?berschriften:
    Zeiger zur ?bergabe von Variablen an Funktionen
    Zeiger zur ?bergabe von Objekten bzw. Objektteilen
    Zeiger zur ?bergabe von Funktionen

    Beitrag ge?ndert am Thu, 06.01.2005 18:57 von 0-checka
  10. g***********r

    Hi cursed!

    Di Antwort vom 0-checka ist sehr ausf?hrlich, und (bis auf seine bislang noch fehlenden Erg?nzungen auch) sehr gut ... wenn Du ejdoch noch wirklich keinen Plan von Zeigern hast, k?nnte es Dich also ein bisschen erschlagen.

    Du kannst Dir einen Zeiger wie eine "normale" Variable vorstellen. Nur dass der Inhalt der Variablen nicht ein Wert (z.b. '123'), sondern die Adresse einer anderen Variablen ist.

    Das bedeutet, wenn Du folgende Variablen hast:
    int a = 135;
    int *b = &a;

    zeigt b auf a!!!!!

    alles was Du mit a machst (z.B. a++;) gilt automatisch auch f?r b.

    Da b aber ein Zeiger ist, kannst Du nicht mit b = 5; b einen neuen WErt zuweisen, sondern musst ihn "derefferenzieren" - sprich aufl?sen:

    *b = 5;

    jetzt sind a und b (selber Speicher) beide 5 !!

    bei "noramlen" int's macht das Spiel wenig sinn, aber beim ?bergeben von gro?en strukturen (z.b. eine neue Klasse) in eine Funktion wird nicht die ganze Klasse kopiert, sondern bleibt nur 1x im Speicher stehn, und es wird nur der Speicher kopiert. Damit kann ein Unterprogramm einfach Variablen im Hauptprogramm ?ndern oder z.B. Dein gesamter Code deutlich Speichereffizienter und damit schneller gemacht werden.

    Weitere Beispiele siehe 0-Checka !!!
  11. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!