Pointer, Enum, Linksschieben und paar andere Noob Fragen



  • schwarztee schrieb:

    5.)
    int m=0, n=1;
    if (m=n)
    m+=2;
    else
    m+=4;
    cout << m << endl; (=3)

    In diesem Fall wird meiner Meinung nach der else ausgeführt und dadurch wird m=4 aber das Ergebniss ist m=3 ?? Echt ratlos.

    Hier fehlt in der Bedingung ein '=': if(m == n).
    So wie es jetzt da steht, wird so ich es denn richtig verstanden habe auf m geprüft, also sozusagen if(m), nur dass m noch der Wert von n zugewiesen wird.

    Edit: too late 🙂



  • Ok dankeschön ihr habt mir echt weiter geholfen vorallem lagalopex.

    Dennoch muss ich sagen das ich die 3.) nicht verstehe, alle anderen habe ich jetzt zu 100% drauf, aber bei dem enum stehe ich da immer noch mit einem Fragezeichen da. 😃

    ps: Das mit dem d=42 stand echt ganz am Anfang der Aufgabe, habe nur paar Teile davon kopiert die ich nicht verstanden habe, habe es übersehen und die 110 oh mein Gott, mit was für Tricks hier gearbeitet wird (haha). Freu mich schon auf die Prüfung. -.-

    Um vielleicht noch eine Aufgabe reinzuwerfen, die war auch Teil der Klausur. Ich dachte die wäre mir klar wenn ich die anderen Zeiger Aufageben verstehe, aber dem ist leider nicht so.

    Aufgabe:

    void funktion1
    (int aa, int *bb, int *cc, int &dd)
    { 
    aa++; *bb++; (*cc)++; dd++;
    }
    
    int aa=0, bb=0, cc=0, dd=0;
    funktion1 (aa, &bb, &cc, dd);
    cout << aa << endl; // =0
    cout << bb << endl; // =0
    cout << cc << endl; // =1
    cout << dd << endl; // =1
    

    Immer diese blöden Zeiger 😞



  • Nochmal zum enum:

    enum {richtig, falsch};
    

    Ist dasselbe wie

    enum {richtig = 0, falsch = 1};
    

    Bei if(falsch) wird falsch zum Wert konvertiert, also 1. Und 1 ist true.

    aa wird auf 0 gesetzt und by-Value an die Funktion übergeben. In der Funktion wird nur eine Kopie erhöht, deshalb bleibt a 0.
    bb wird by-Reference (genau genommen via Pointer) an die Funktion übergeben.
    In der Funktion wird *bb++ ausgeführt. Aufgrund der Operator Rangfolge wird zuerst bb++ ausgefüht und auf das Ergebnis davon das *. D.h. bb wird um eine Speicheradresse erhöht (genau genommen UB, da die Speicheradresse nicht offziel belegt ist), und auf die alte Speicheradresse (ist ja Postinkrement) wird der Wert geholt und direkt wieder verworfen.
    Bei cc wird richtig der Wert erhöht, indem Klammern gesetzt werden und cc wird klassich by-Reference übergeben und erhöht.



  • Ok, dank dir, enum ist jetzt klar, war echt verwirrennd wegen den Namen.

    Aber beim anderen verstehe ich nur Bahnhof, habe die Begriffe nie gehört, auch das Skript vom Prof. durchsucht und nix gefunden.
    Im Internet dann das gefunden http://de.m.wikibooks.org/wiki/C++-Programmierung/_Weitere_Grundelemente/_Prozeduren_und_Funktionen aber wirklich verstehen tu ich es nicht.

    Falls irgendjemand noch ein Rat hat, bitte her damit. 👍

    Müsste die Zeile 7 nicht alle Werte auf 0 setzen?
    Und was genau macht eigentlich die Zeile 8?



  • schwarztee schrieb:

    Und was genau macht eigentlich die Zeile 8?

    Keines deiner Beispiele hat 8 Zeilen.



  • nwp3 schrieb:

    schwarztee schrieb:

    Und was genau macht eigentlich die Zeile 8?

    Keines deiner Beispiele hat 8 Zeilen.

    Meine das hier:

    void funktion1
    (int aa, int *bb, int *cc, int &dd)
    { 
    aa++; *bb++; (*cc)++; dd++;
    }
    
    int aa=0, bb=0, cc=0, dd=0;
    funktion1 (aa, &bb, &cc, dd);
    cout << aa << endl; // =0
    cout << bb << endl; // =0
    cout << cc << endl; // =1
    cout << dd << endl; // =1
    

    Hab bis jetzt alles verstanden ausser diese by-Values und by-Reference usw.



  • schwarztee schrieb:

    void funktion1
    (int aa, int *bb, int *cc, int &dd)
    { 
    aa++; *bb++; (*cc)++; dd++;
    }
    
    int aa=0, bb=0, cc=0, dd=0;
    funktion1 (aa, &bb, &cc, dd);
    cout << aa << endl; // =0
    cout << bb << endl; // =0
    cout << cc << endl; // =1
    cout << dd << endl; // =1
    

    In Zeile 8 wird die Funktion funktion1 aufgerufen. Die Paramter sind aa , die Adresse von bb und cc , sowie dd .

    In der Funktion gibt es nun ein neues aa welches nur den Wert vom ursprünglichen aa hat. Dann zwei Zeiger bb und cc die auf das ursprüngliche bb bzw cc zeigen. Sowie dd welches praktisch identisch ist mit dem anderen dd .

    In der Funktion wird aa geändert, da es aber nur eine Kopie ist, die geändert wird, ändert sich das ursprüngliche aa nicht. (Es bleibt null.)
    Der Zeiger bb wird um eins erhöht, es würde also auf einen Integer hinter dem ursprünglichen bb zeigen. Dieser Wert wird geholt (was dabei rauskommt ist nicht definiert) aber der Wert wird eh verworfen. (Auch das zweite bleibt null.)
    Mit (*cc)++ wird nun der Wert, auf den cc zeigt geholt und um eins erhöht. Dies ist gerade das ursprüngliche cc . (Es wird eins ausgegeben.)
    Das dd ist nun eine Referenz auf das ursprüngliche dd und verhält sich genauso. Die Änderung beeinflusst also direkt das ursprüngliche dd . (Es wird wieder eine eins ausgegeben.)

    By-Value meint, dass das Objekt kopiert wird und nur der Wert übergeben wird.
    By-Referenz hingegen übergibt das Original, so das es in der Funktion geändert werden kann.
    Die Zeiger sind so ein zwischending, es wird der Wert (die Adresse) by-Value übergeben, aber über die Adresse kann das Original geändert werden.



  • Tur mir Leid aber ich verstehe es einfach nicht, hab jetzt alles mögliche darüber gelesen aber ich verlier einfach den Überblick.

    void funktion1
    (int aa, int *bb, int *cc, int &dd)
    { 
    aa++; *bb++; (*cc)++; dd++;
    }
    
    int aa=0, bb=0, cc=0, dd=0;
    funktion1 (aa, &bb, &cc, dd);
    cout << aa << endl; // =0
    cout << bb << endl; // =0
    cout << cc << endl; // =1
    cout << dd << endl; // =1
    

    Also ich beschreibe mal wie weit ich mit komme, evtl. wissen wir dann wo bei mir im Gehirn es einfach stoppt.

    Zeile 1: Die Funktion "funktion1" wird deklariert.
    Zeile 2: Integer aa wird deklariert, Zeiger von bb und cc wird deklariert, Referenz von dd wird deklariert.
    Zeile 4: Anweisungen aa++, *bb++, (*cc)++, dd++ werden definiert.
    Zeile 7: Weiß ich nicht so genau was die macht. Ist die überhaupt relevant? (?)
    Zeile 8: Da hackt es richtig, ich weiß nicht genau was das mir sagen soll, warum macht man das? Was nützt das?

    Ich kapier es nicht, wird jetzt (Zeile 😎 alles neu deklariert?

    Und wo ist der Unterschied zwischen *bb++ und (*cc)++, was bringt die Klammer? (Zeile 4)

    Werden hier die Werte um 1 erhöht, postinkrement. Wie das wenn man nicht weiß welche Werte aa, bb, cc und dd haben. (Zeile 4)



  • schwarztee schrieb:

    Zeile 1: Die Funktion "funktion1" wird deklariert.

    Nein, das ist der Beginn einer Definition. Eine Funktionsdeklaration sieht so aus:

    void funktion(int aa, int *bb); // z.B.
    

    Zeile 2: Integer aa wird deklariert, Zeiger von bb und cc wird deklariert, Referenz von dd wird deklariert.

    Ja, aber ganz wichtig: Als Parameter der Funktion. Diese Variablen werden beim Aufruf der Funktion mit Werten versehen und sind nur innerhalb des Funktionskörpers gültig.

    Zeile 4: Anweisungen aa++, *bb++, (*cc)++, dd++ werden definiert.

    Ja. Wobei das komisch klingt. Die Zeile besteht aus den Anweisungen selbst, nicht aus "Definitionen" dieser Anweisungen.

    Zeile 7: Weiß ich nicht so genau was die macht. Ist die überhaupt relevant? (?)

    Das sind die Deklarationen der Variablen aa bis dd. Ohne das gibts die nicht. Das sind völlig andere Variablen als die Funktionsparameter oben, auch wenn sie gleich heißen mögen. Wenn dich das verwirrt, benenne sie (oder die Parameter) temporär anders.

    Zeile 8: Da hackt es richtig, ich weiß nicht genau was das mir sagen soll, warum macht man das? Was nützt das?

    Das ist der Aufruf der Funktion. Die Parameter werden mit den übergebenen Argumenten initialisiert, dann wird der Körper der Funktion ausgeführt, dann geht es nach der Aufrufstelle weiter.

    Ich kapier es nicht, wird jetzt (Zeile 😎 alles neu deklariert?

    Nein, das ist keine Deklaration.

    Und wo ist der Unterschied zwischen *bb++ und (*cc)++, was bringt die Klammer? (Zeile 4)

    Der nachgestellte ++-Operator hat eine höhere Priorität, d.h. *bb++ wird wie *(b++) interpretiert.

    Werden hier die Werte um 1 erhöht, postinkrement. Wie das wenn man nicht weiß welche Werte aa, bb, cc und dd haben. (Zeile 4)

    Weiß man doch, steht doch alles da.



  • Zeile 7 sagt "Es gibt vom Typ int eine Variable aa mit Startwert 0, eine Variable bb mit Startwert 0, ..."
    Die Variablen von Zeile 7 haben mit den Parameternamen in Zeile 2 garnichts zu tun.

    Zeile 8 ruft die Funktion funktion1 auf. funktion1 benötigt für den Aufruf ein int, ein int *, noch ein int * und ein int & wie in Zeile 2 definiert.
    Ein int ist eine Zahl. Ein int * ist ein Zeiger auf eine Zahl. Ein int & ist ein anderer Name für ein int.
    Um nun funktion1 aufzurufen brauchen wir zuerst ein int. Kein Problem, aa ist ein int, steht in Zeile 7. Dann brauchen wir einen Zeiger auf ein int. bb ist ein int und kein Zeiger auf ein int. Mit &bb bekommst du die Adresse von bb. Mit der Adresse der Variablen bb (ein int) kann man den Parameter bb (ein int 😉 initialisieren. Parameter bb zeigt jetzt auf Variable bb.
    Parameter dd ist jetzt ein anderer Name für die Variable dd. Das ist sinnvoll, weil funktion1 nicht direkt auf Variable dd zugreifen kann, weil zur Zeit der Definition die Variable dd noch gar nicht deklariert ist.
    Dann Zeile 4: aa++ erhöht den Parameter aa. Die Variable aa ist nicht betroffen, nur der Parameter aa, deswegen gibt das Programm zuerst eine 0 aus. Dann kommt der Ausdruck *bb++. bb ist ein Zeiger auf einen int. *bb dereferenziert Parameter bb, sodass du zu dem int kommst auf das Parameter bb zeigt (zufälligerweise Variable bb). Die Vorrangregeln in C++ sagen, dass zuerst bb++ und danach die Dereferenzierung ausgeführt werden. bb++ erhöht den Zeiger bb um 1, sodass es jetzt auf Blödsinn zeigt. Der Ausdruck bb++ hat als Rückgabewert bb, vor der Inkrementierung. Danach wird bb dereferenziert und man landet bei Variable bb. Und damit wird nichts gemacht. Also ist Variable bb am Ende immernoch 0, weil es nicht geändert wurde.
    (*cc)++ ändert mit den Klammern die Reihenfolge. Zuerst wird cc dereferenziert und wir landen bei Variable cc. Dann wird diese Variable um 1 erhöht.
    Zuletzt wird Parameter dd erhöht. Parameter dd ist nur ein anderer Name für Variable dd, also haben wir Variable dd um 1 erhöht.

    Wichtig zu merken: Variablennamen und Parameternamen sind unabhängig und werden unabhängig voneinander verändert. Zeiger muss man dereferenzieren wenn man an das rankommen will, worauf sie zeigen.



  • Ich hab jetzt mal eine Nacht drüber geschlafen, und natürlich wieder meine typischen C++ Albträume gehabt. 😃

    Und mit klarem Kopf wird einiges klarer, ich verstehe nicht alles zu 100% aber so viel das es eigentlich reichen müsste, ich hoffe so eine Art von Aufgabe wird nicht nächste Woche in der Klausur dran kommen, wenn nicht muss ich mich halt an der jetzigen Aufgabe orientieren.

    Ich danke euch allen sehr vom Herzen, falls man sich mal im Real Life sieht geb ich auch ein Bier aus. 😉

    Schönen Tag euch allen noch.
    schwarztee. 👍


Anmelden zum Antworten