zeiger für anfänger



  • hallo,

    ich verstehe das mit den zeigern nicht:/.

    also ich mache einen zeiger der auf eine adresse zeigt, in der
    adresse speicher ich einen wert und kann den über den pointer
    auslesen?

    #include <iostream.h>
    
    test(int*);
    
    void main(int* p)
    {
    	char x;
    	cout<< *p <<endl;
    	cin>>x;
    }
    
    test(int*)
    {
    	int i=4, *p;
    	p=&i;
    }
    

    acess violation. wie kann ich den wert aus der funktion lesen?
    kann das mal jemand umsetzen mit pointer bitte? hoffe erklährt sich
    dann für mich von selbst.

    #include <iostream.h>
    
    int eingabe();
    int verarbeitung();
    ausgabe();
    
    int a, b, er;
    
    void main(void)
    {
    	char x;
    	eingabe();
    	verarbeitung();
    	ausgabe();
    	cin>>x;
    }
    
    int eingabe()
    {
    	cin>>a;
    	cin>>b;
    	return (a,b);
    }
    
    int verarbeitung()
    {
    	er=a+b;
    	return(er);
    }
    
    ausgabe()
    {
    	cout<<a<<"+"<<b<<"="<<er<<endl;
    }
    

    danke schonmal an euch.

    mfg stephan



  • Hi,
    ich hab das mit den Zeigern auch erst nicht so richtig verstanden aber dann habe ich viel mit Zeigern programmiert dann wieder nachgeschlagen usw.

    Ich hab das ungefähr so verstanden:
    (kleines Beispiel Prog.)

    [cpp]
    #include <iostream.h>
    #include <stdio.h>

    int main() {

    int *ptr = NULL;// Zeiger auf int damit sagst du eigentlich nur das der
    // Zeiger auf ein int Objekt zeigen wird. Deshalb kannst
    // du auch nicht einen char Zeiger auf ein int Objekt
    // Zeigen lassen! Da der Compiler int Objekte auf 32-Bit
    // Systemen in ( ich glaube ) 4-Bit codiert und char
    // Objekte auf 8-Bit. Die NULL bedeutet das du den Zeiger
    // noch nicht referenzierst d.h. ihm keiner Addresse
    // zuweist sonst zeigt er irgendwo in den Speicher und
    // vielleicht sogar vom Betriebssystem und das ist nicht
    // schön besonders wenn du ihm jetzt einen Wert zuweist
    // und er die benötigten Ressourcen vom Betriebssystem
    // überschreibt.
    int var = 10;

    ptr = &var; // Damit gibst du dem Zeiger ptr die Referenz bzw die
    // Addresse von var.

    cout << *ptr << endl; // Wenn du ein Sternchen davor setzt weiß der
    // Compiler das du auf das Objekt zugreifen
    // willst worauf der Zeiger zeigt und nicht
    // direkt auf den Zeiger.
    cout << ptr << endl; // Jetzt gibt er das aus was in dem Zeiger steht
    // das ist meistens die Addresse worauf er
    // zeigt ( wenn du ihn mit NULL initalisierst
    // wird der hexidezimale Code der Addresse
    // ausgegeben ).
    // Zeiger sind fast genauso wie Variablen.
    return 0;
    }[/cpp]

    Ich hab dir grad n kleines Buch geschrieben :p ist mir grad so aufgefallen
    aber hoffe lernst draus.

    Bis dann
    Cl0v3r

    P.S.: Ach und wieso gibst du der Funktion ausgabe() keinen Typ oder Wert? Naja
    ich hab dir das mal eben mit Zeigern umgeschrieben.
    Ungefähr so:

    #include <iostream.h>
    
    int eingabe();
    int verarbeitung();
    int ausgabe();
    
    int *a_ptr = NULL;
    int *b_ptr = NULL;
    int *er_ptr = NULL;
    
    int a;
    int b;
    int er;
    
    void main(void)
    {
        eingabe();
        verarbeitung();
        ausgabe();
    }
    
    int eingabe()
    {
    	a_ptr = &a;
    	b_ptr = &b;
    
        cin >> *a_ptr;
        cin >> *b_ptr;
        return (*a_ptr,*b_ptr);
    }
    
    int verarbeitung()
    {
        er_ptr = &er;
        *er_ptr = *a_ptr + *b_ptr;
        return(*er_ptr);
    }
    
    int ausgabe()
    {
        cout<<*a_ptr<<"+"<<*b_ptr<<"="<<*er_ptr<<endl;
    	return 0;
    }
    

    Bisch dann
    Cl0v3r



  • hallo

    das ich schön was Cl0v3r geschrieben hat aber ob das alles stimmt mmh?
    gibt´s Befürworter oder Gegner?
    andere Meinungen dazu ?
    Danke



  • Er hat recht, soweit ich das jetzt überfolgen habe.
    Allerdings sint Integer 32 bit (auf 32bit Systemen).



  • ein zeiger ist immer 4 byte groß

    [cpp]

    int main ()
    {
    int *p;
    int a=10;

    p = &a;

    // *P und a haben jetzt immer den selben Wert, weil p und &a auf die gleiche adresse im Speicher zeigen,
    // d.h. wenn du einen Wert änderst, ändert sich der andere Wert auch.

    cout << "P=" << *p << endl;
    cout << "A=" << a << endl;

    a = 5;

    cout << "P=" << *p << endl;
    cout << "A=" << a << endl;

    *p = 789;

    cout << "P=" << *p << endl;
    cout << "A=" << a << endl;

    return 0;
    }
    [/cpp]

    wenn du variablen in einer funktion ändern willst, übergibst du die variable als referenz (Stichworte: call by ref, call by value).

    Beispiel:

    void func1 (int p);
    void func2 (int *p);
    
    int main ()
    {
        int a = 10;
    
        func1 (a);
        cout << "A nach func1" << a << endl;
    
        func2 (&a);
        cout << "A nach func2" << a << endl;
    
        return 0;
    }
    
    void func1 (int p)
    {
        cout << "func1, p = " << p << endl;
    
        p = 10;
    
        cout << "func1, p = " << p << endl;
    }
    
    void func2 (int *p)
    {
        cout << "func2, p = " << *p << endl;
    
        *p = 123;
    
        cout << "func2, p = " << *p << endl;
    }
    

    Hoffe dies verdeutlicht es dir ein wenig (nicht getestet)

    Gruß
    Horst

    PS: Was immer hilft ist ein tut oder ein buch, da sind genau solche beispiele drinne 😃



  • Zeiger sind nur auf 32 Bit Systemen in der Regel mit 32 Bit (4 Byte) realisiert. Man muss Zeiger nicht mit NULL (#define NULL 0) initialisieren und kann ihnen einfach sofort eine gültige Adresse zuweisen. Wenn ein Zeiger keine gültige Adresse hat, sollte man ihn aber nicht dereferenzieren. NULL wird z.Bsp. verwendet, wenn eine Suchfunktion einen Zeiger zurückgeben soll, aber nichts findet. Dann kann das Ergebnis mit NULL verglichen und so die Gültigkeit des Zeigers abgefragt werden. Hier noch ein kleineres Beispiel mit Zeigern:

    #include <iostream> // iostream.h ist veraltet
    
    using namespace std; // damit man das std:: bei std::cout, std::cin, std::endl, ... weglassen kann
    
    template<typename T>
    inline T *min(T *x, T *y)
    {
        // x ist die Adresse des Wertes, auf den x zeigt
        // (*x) bezieht sich auf den Wert, der in der Adresse steht, auf die x zeigt (dereferenzieren des Zeigers x)    
        return *x>*y?y:x;
    }
    
    int main() // main muss int als Rückgabe haben
    {   
        int a=12, b=5, *zeiger;
    
        zeiger = min(&a, &b);
        *zeiger = 7;
    
        zeiger = &a;
        *zeiger /= 3;
    
        cout<<"a:"<<a<<endl<<"b:"<<b<<endl;
        cin.get();
    
        //hier passiert automatisch: return 0;
    }
    


  • hallo
    was ich gemerkt hab es gibt einen Konflikt zw. C und C++ programmierer .
    wo sind die Experten ?
    was sagt Humesikkins zu diesem Beitrag?



  • Cl0v3r schrieb:

    // [...]          Da der Compiler int Objekte auf 32-Bit
                        // Systemen in ( ich glaube ) 4-Bit codiert und char 
                        // Objekte auf 8-Bit.
    

    😕

    Cl0v3r schrieb:

    // [...]              Die NULL bedeutet das du den Zeiger
                        // noch nicht referenzierst d.h. ihm keiner Addresse 
                        // zuweist sonst zeigt er irgendwo in den Speicher
    

    Nicht ganz. Es wird schon eine Adresse zugewiesen. Der Zeiger hat also einen definierten Wert und zeigt nicht irgendwo hin. Wie der Wert genau aussieht, ist allerdings plattform-spezifisch.

    Horst2 schrieb:

    ein zeiger ist immer 4 byte groß

    Nö!



  • hm, also ich bin mir zwar jetzt auch nicht so ganz sicher, ob alles richtig ist, was ich schreibe, aber ich schreib's trotzdem mal. 🙂

    Zeiger sind immer so groß, wie die Architektur es vorgibt, also auf 32bit-Systemen 32 Bit (4 Bytes) und auf 64bit-System halt 64 Bit (8 Bytes).

    Eine Referenz auf ein Objekt ist im Prinzip einfach nur ein zweiter Variablenname für ein Objekt, dieser zweite Name kann natürlich einen anderen Gültigkeitsbereich haben, wie der erste (call-by-reference).

    #include <iostream>
    
    using namespace std;
    
    void test1(int &a) {
      a = 3;
    }
    
    int main() {
    
    	int b;
    	test1(b);
    
    	cout << "b: " << b << endl;
    
    	return 0;
    }
    

    Hier ist a nur innerhalb der Funktion test1 gültig, ändert aber den Wert der Variablen, der beim Aufruf (hier b) übergeben wird und zwar per Referenz. Die Funktion muss nicht prüfen, ob die übergebene Variable a gültig ist, das übernimmt der Compiler. Außerdem kann ich innerhalb der Funktion ganz normal mit der Variablen arbeiten.

    Bei Zeigern sieht das etwas anders aus:

    #include <iostream>
    
    using namespace std;
    
    void test2(int *a) {
    	if (a != NULL) {
    		*a = 3;
    	}
    	else {
    		cerr << "Error: Null-Referenz" << endl;
    	}
    }
    
    int main() {
    
    	int b;
    	test2(0);
    	test2(&b);
    
    	cout << "b: " << b << endl;
    
    	return 0;
    }
    

    Hier wird der Funktion test2 ein Zeiger auf b mit dem Adressoperator & übergeben, da eine Adresse auch Null sein kann muss hier geprüft werden, ob dies der Fall ist, da ansonsten ein dereferenzieren des Zeigers mit *a nicht möglich ist (s. Aufruf test2(0)). NULL ist gleichbedeutend mit 0. Bei Zeigern muss man noch beachten, dass, wenn wir nu den Zeiger a aus test2 nehmen eine Zuweisung "a = ..." nicht den Inhalt von b ändert, sondern die Adresse von a, a somit irgendwo anders hinzeigt. Wenn man den Inhalt ändern möchte, dann muss man den Zeiger mit *a dereferenzieren.

    Im Grunde sind Zeiger etwas komplizierter als Referenzen, und ich habe mal gehört, dass man immer Referenzen nehmen sollte, wenn man nicht unbedingt einen Zeiger braucht, aber mit Zeigern lassen sich auch schöne Dinge machen, da man sie ziemlich frei im Speicher bewegen und "umbiegen" kann. 🙂

    Ich hoffe es war alles richtig und es ist etwas klarer geworden. 🙂



  • Danke für Eure Zahlreichen Antworten!

    Ich hab zwar schon 3 Bücher zum Thema c++, aber manchmal
    sind Beschreibungen von anderen einfach besser.

    Vieles sieht für mich immernoch wie Chinesich aus, wenn
    ich mir einige Quelltexte anschaue. Da zeigen Zeiger dann auf andere
    Funktionen in anderen Dateien, mit ** und &&..... naja muss noch viel
    lernen. werde mir wohl noch 2 Bücher kaufen.

    Sind die Bücher c++ für dummies und OOP für dummies gut?
    Die werden grad im doppelpack angeboten.

    MfG Stephan



  • noob schrieb:

    Vieles sieht für mich immernoch wie Chinesich aus, wenn
    ich mir einige Quelltexte anschaue. Da zeigen Zeiger dann auf andere
    Funktionen in anderen Dateien, mit ** und &&..... naja muss noch viel
    lernen. werde mir wohl noch 2 Bücher kaufen.

    Vielleicht hilft dir dazu auch noch dieser C++-FAQ Beitrag weiter. Meines Erachtens sehr schön geschrieben bzw. erklärt.

    Sind die Bücher c++ für dummies und OOP für dummies gut?
    Die werden grad im doppelpack angeboten.

    Speziell zu diesen Büchern kann ich nichts sagen, würde dir aber das Buch "C++ lernen und professionell anwenden" von Peter Prinz und Ulla-Kirch Prinz ans Herz legen.
    Desweiteren bzg. Buchempfehlungen bzw. Buch-Favoriten siehe http://www.c-plusplus.net/forum/search/log.php?url=http://www.c-plusplus.net/forum/viewtopic-var-t-is-94151.html und/oder die Bücherseite.

    Caipi



  • Da der Compiler int Objekte auf 32-Bit
    // Systemen in ( ich glaube ) 4-Bit codiert und char
    // Objekte auf 8-Bit.

    Oh mein Gott, was hab ich denn da geschrieben? War wohl schon etwas müde :p

    Im Grunde sind Zeiger etwas komplizierter als Referenzen, und ich habe mal gehört, dass man immer Referenzen nehmen sollte, wenn man nicht unbedingt einen Zeiger braucht, aber mit Zeigern lassen sich auch schöne Dinge machen, da man sie ziemlich frei im Speicher bewegen und "umbiegen" kann. 🙂

    Und gefährlich wenn ich das mal anmerken darf 😉 Aber du hast recht.
    Macht richtig Phun mit Zeigern zu Progsn.

    Bisch dann
    Cl0v3r



  • danke an euch 🙂

    mit den einfachen pointern und referenzen hab ich jetzt verstanden.
    (hoff ich)

    #include <iostream>
    
    using namespace std;
    
    void eingabe(int *w_1, int *w_2);
    void verarbeitung(int *w1, int *w2, int *w3);
    void ausgabe(int *erg);
    
    int main(void)
    {
    	int w1_a, w2_b, er;
    	char x;
    
    	er=0;
    	w1_a=0;
    	w2_b=0;
    
    	eingabe(&w1_a, &w2_b);
    	verarbeitung(&w1_a, &w2_b, &er);
    	ausgabe(&er);	
    
    	cin.get();
    	cin>>x;
    
    	return 0;
    }
    
    void eingabe(int *w_1, int *w_2)
    {
    	cin>>*w_1;
    	cin>>*w_2;
    }
    
    void verarbeitung (int *w1, int *w2, int *w3)
    {
    	*w3=*w1+*w2;
    }
    
    void ausgabe(int *erg)
    {
    	cout<< "ergebnis= "<< *erg << endl;
    }
    

    sieht vielleicht noch nich optimal aus, aber es klappt 🙂


Log in to reply