Zeiger und Referenzen in C + + Teil 1
Zeiger und Referenzen sind zwei sehr wichtige Konzepte der Informatik. Sie erscheinen in vielen Programmiersprachen mit einem Kleid oder ein wenig anders, aber die Behandlung ist im Grunde das gleiche. In C + +, Zeiger sind wichtige Fähigkeiten.
Pointer ist eine besondere Art von Daten, deren Variablen können wie in (oder nicht), einige andere Daten im Speicher erklärt. Eine Variable vom Typ Zeiger die Adresse einer anderen Sache in Erinnerung. Dieses Ding kann jede Variable, Konstante, der Anfang eines Datensatzes, eine Funktion, unter anderem werden.
Zeiger deklarieren
Die Deklaration eines Zeigers ist in der Regel durch Zugabe von a * vor dem Variablennamen getan. Eine weit verbreitete Schreibweise *, um den Namen des Typs zu sagen, dass wir symbolisch erklärt ein "Zeiger auf den Typ" anstelle von "Zeiger-Variable", aber sie sind gleichwertig einfügen. Zum Beispiel:
/ / Zeiger auf ein int. ptr_num1 ; int * ptr_num1; / / Oder so. ptr_num2 ; int * ptr_num2; / / Zeiger auf ein Doppelzimmer. ptr_double1 ; double * ptr_double1; / / Oder so. ptr_double2 ; double * ptr_double2;
Einmal erklärt, wird der Zeiger existiert, hat die Länge und erfolgt somit in Erinnerung. Die Größe eines Zeigers ist in der Regel gleich der Anzahl von Bits der Maschine / Anlage, z. B. 4 Byte in einem 32-Bit-System.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 | pc ; int i, * pi ; double d, * pd ; // O operador sizeof diz o tamanho do tipo do seu argumento. cout << "Size of char: " << sizeof ( c ) << " bytes" << endl ; cout << "Size of int: " << sizeof ( i ) << " bytes" << endl ; cout << "Size of double: " << sizeof ( d ) << " bytes" << endl ; cout << endl ; cout << "Size of char*: " << sizeof ( pc ) << " bytes" << endl ; cout << "Size of int*: " << sizeof ( pi ) << " bytes" << endl ; cout << "Size of double*: " << sizeof ( pd ) << " bytes" << endl ; char c, * pc, int i, * pi-, Doppel-d, pd * / / Der Operator sizeof, sagt die Größe von der Art ihrer Argumentation cout <<"Größe von char:". <<sizeof (c) <<" bytes "<<endl; cout <<" Größe von int: "<<sizeof (i) <<" Bytes "<<endl; cout <<" Größe von double: "<<sizeof (d) <<" Bytes " <<endl; cout <<endl; cout <<"Größe von char *:" <<sizeof (cp) <<"Bytes" <<endl; cout <<"Größe von int *:" <<sizeof (pi) <<"Bytes" <<endl; cout <<"* Größe von double:" <<sizeof (pd) <<"Bytes" <<endl; |
Mit Pointers
Nach seiner Aussage ist der Inhalt eines Zeigers einen zufälligen Wert, Verschwendung von Speicher, wie jede andere Variable. Denn es werden, um brauchbare wir brauchen, um etwas zu ordnen. Als Zeiger speichert eine Speicher-Adresse, müssen wir weisen Sie eine gültige Adresse.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | int x, y; px, * py ; int * px, * py; ; x = 13; ; y = 10; x ; & X = px; y ; & Y = py; 42 ; * Px = 42; py ) ++ ; (* Py) + +; * px << endl ; cout <<* px <<endl; * py << endl ; cout <<* py <<endl; ( * px ) * ( * py ) << endl ; cout <<(* px) * (* py) <<endl; |
Der Operator & (kaufmännisches oder kaufmännisches ), bevor eine Variable Name bedeutet "die Adresse", denn sein Name ist "Adresse".
Was ist der Gleichheit verlassen hat, um der Lage sein, genau die gleiche Art, auf der anderen Seite der Gleichheit zu halten. Ein Zeiger hält eine Ansprache. So, um eine Adresse zu einem Zeiger in diesem Fall müssen Sie eine Adresse mit der &-Operator zu erhalten.
Außer im Falle, wo es implizite Typumwandlung (wie z. B. zwischen numerischen Typen), weisen eine Variable, um etwas mit einer anderen Art von Ihnen, zu einem Kompilierungsfehler. Zum Glück!
Nachdem Sie einen Zeiger auf eine gültige Adresse, wir können den Inhalt dieser Adresse mit dem Betreiber * (Zugang Stern ), dessen offizielle Name ist "de-Referenz-Operator."
Beachten Sie, dass der Stern in einer Erklärung "Zeiger auf den Typ" bezeichnet und im Zusammenhang mit Lesen oder Schreiben der Inhalt eines Zeigers, bedeutet "der Inhalt der Adresse" oder "durch den Inhalt bestimmt." Auch darauf achten, nicht mit dem Symbol für arithmetische Produkt verwechselt werden. Um Verwirrung zu vermeiden, denken Sie daran, dass riesige Tabelle der überwiegenden Betreiber , dass Sie gerade für das Auge und fiel in Vergessenheit. Hier finden Sie, dass der Betreiber-Referenz Vorrang vor der Multiplikation Betreiber. Done, dass Sie sich erinnern, dass die de-Referenz-Operator vor der Multiplikation Betreiber ausgewertet wird.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 | pa, * pb ; int a, b, c, * pa, * pb; ; a = 2; ; b = 3; a ; pa = & a; b ; bp = & b; pa * * pb ; c = * pa * pb; pa * * pb ; c = * pa * pb; pa * * pb ; c = * pa * pb; pa ** pb ; ** C * pa = pb; * pa ) * ( * pb ) ; c = (* pa) * (* bp); "Valor da Pegadinha: " << c << endl ; cout <<"Wert von Gotcha:" <<c <<endl; |
Also, wenn der Nachweis von Algorithmen, die Sie fragen, was macht eine der letzten fünf Zeilen des Beispiels, werden Sie sagen, dass es den Inhalt von PA und PB wies multipliziert. Keine Notwendigkeit mehr, DP dafür bekommen! Und brechen im wirklichen Leben, wenn Sie wirklich brauchen, um dies zu tun, sparen Sie Ihre 4 Generationen Vergangenheit und Zukunft von 5 Exkommunikation , wenn man die letzte Zeile verwenden möchten.
Alles, was Sie mit einem gemeinsamen Variablen, die Sie mit den Inhalten tun können, tun können, auf die ein Zeiger, entweder lesen oder schreiben (es sei denn, es ist klar, dass der Zeiger const ist, aber das ist eine andere rant ...).
Adressen und Zeiger
Nehmen Sie den nachfolgenden Code:
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | int a, b; pa, * pb ; int * pa, * pb; "Antes de qualquer atribuição: \n " ) ; printf ("Vor jedem Auftrag: \ n"); "&a = %p \n " , & a ) ; // Endereço válido dado pelo SO. printf ("& a =% p \ n", & a) / / Valid-Adresse des OS gegeben. "&b = %p \n " , & b ) ; // Endereço válido dado pelo SO. printf ("& b =% p \ n", & b) / / Valid-Adresse des OS gegeben. "&pa = %p \n " , & pa ) ; // Endereço válido dado pelo SO. printf ("& ap =% p \ n", & pa), / / Adresse als gültig vom OS. "&pb = %p \n " , & pb ) ; // Endereço válido dado pelo SO. printf ("& sc =% p \ n", & bp) / / Valid-Adresse des OS gegeben. " \n " ) ; printf ("\ n"); "a = %d \n " , a ) ; // Conteúdo não inicializado (aleatório). printf ("a =% d \ n", a) / / Content initialisierte (random). "b = %d \n " , b ) ; // Conteúdo não inicializado (aleatório). printf ("b =% d \ n", b) / / Content initialisierte (random). "pa = %p \n " , pa ) ; // Conteúdo não inicializado (aleatório). printf ("pa =% p \ n", pa) / / Content initialisierte (random). "pb = %p \n " , pb ) ; // Conteúdo não inicializado (aleatório). printf ("sc =% p \ n", bp) / / Content initialisierte (random). / / Probieren Sie die Aktivierung der beiden folgenden Zeilen ein, kompilieren und ausführen. / / Printf ("* pa =% d \ n", * pa) / / Was ist (random *)? / / Printf ("* bp =% d \ n", * bp) / / Was ist (random *)? " \n Após as inicializações dos ponteiros: \n " ) ; printf ("\ n Nach der Initialisierung von Zeigern: \ n"); a ; pa = & a; b ; bp = & b; "&a = %p \n " , & a ) ; // Mesmo endereço válido dado pelo SO. printf ("& a =% p \ n", & a) / / Noch gültige Adresse des OS gegeben. "&b = %p \n " , & b ) ; // Mesmo endereço válido dado pelo SO. printf ("& b =% p \ n", & b) / / Noch gültige Adresse des OS gegeben. "&pa = %p \n " , & pa ) ; // Mesmo endereço válido dado pelo SO. printf ("& ap =% p \ n", & pa) / / Noch gültige Adresse des OS gegeben. "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ("& sc =% p \ n", & bp) / / Noch gültige Adresse des OS gegeben. " \n " ) ; printf ("\ n"); "a = %d \n " , a ) ; // Conteúdo não inicializado (aleatório). printf ("a =% d \ n", a) / / Content initialisierte (random). "b = %d \n " , b ) ; // Conteúdo não inicializado (aleatório). printf ("b =% d \ n", b) / / Content initialisierte (random). "pa = %p \n " , pa ) ; // Conteúdo inicializado (&a). printf ("pa =% p \ n", pa) / / initialisiert Content (& a). "pb = %p \n " , pb ) ; // Conteúdo inicializado (&b). printf ("sc =% p \ n", bp) / / Content starts (& b). "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa (*pa == a). printf ("* pa =% d \ n", * pa) / / Content von pa ernannt (pa == * a). "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (*pb == b). printf ("* bp =% d \ n", * bp) / /, auf den Inhalt bp (bp * == b). " \n Após as inicializações dos inteiros: \n " ) ; printf ("\ n Nach der Initialisierung der ganzen Zahlen: \ n"); ; a = 10; ; b = 13; "&a = %p \n " , & a ) ; // Mesmo endereço válido dado pelo SO. printf ("& a =% p \ n", & a) / / Noch gültige Adresse des OS gegeben. "&b = %p \n " , & b ) ; // Mesmo endereço válido dado pelo SO. printf ("& b =% p \ n", & b) / / Noch gültige Adresse des OS gegeben. "&pa = %p \n " , & pa ) ; // Mesmo endereço válido dado pelo SO. printf ("& ap =% p \ n", & pa) / / Noch gültige Adresse des OS gegeben. "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ("& sc =% p \ n", & bp) / / Noch gültige Adresse des OS gegeben. " \n " ) ; printf ("\ n"); "a = %d \n " , a ) ; // Conteúdo inicializado (10). printf ("a =% d \ n", a) / / initialisiert Inhalt (10). "b = %d \n " , b ) ; // Conteúdo inicializado (13). printf ("b =% d \ n", b) / / Content initialisiert (13). "pa = %p \n " , pa ) ; // Conteúdo inicializado (&a). printf ("pa =% p \ n", pa) / / initialisiert Content (& a). "pb = %p \n " , pb ) ; // Conteúdo inicializado (&b). printf ("sc =% p \ n", bp) / / Content starts (& b). "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa (*pa == a == 10). printf ("* pa =% d \ n", * pa) / / Content ap wies mit einem (* ap == a == 10). "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (*pb == b == 13). printf ("* bp =% d \ n", * bp) / /, auf den Inhalt bp (bp * == b == 13). " \n Alterando os valores através dos ponteiros: \n " ) ; printf ("\ n Wertewandel über Zeiger: \ n"); 7 ; * Pa = 7; 42 ; * Bp = 42; "&a = %p \n " , & a ) ; // Mesmo endereço válido dado pelo SO. printf ("& a =% p \ n", & a) / / Noch gültige Adresse des OS gegeben. "&b = %p \n " , & b ) ; // Mesmo endereço válido dado pelo SO. printf ("& b =% p \ n", & b) / / Noch gültige Adresse des OS gegeben. "&pa = %p \n " , & pa ) ; // Mesmo endereço válido dado pelo SO. printf ("& ap =% p \ n", & pa) / / Noch gültige Adresse des OS gegeben. "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ("& sc =% p \ n", & bp) / / Noch gültige Adresse des OS gegeben. " \n " ) ; printf ("\ n"); "a = %d \n " , a ) ; // Conteúdo inicializado (a == *pa == 7). printf ("a =% d \ n", a) / / initialisiert Content (* ap == a == 7). "b = %d \n " , b ) ; // Conteúdo inicializado (b == *pb == 42). printf ("b =% d \ n", b) / / initialisiert Content (* bp == b == 42). "pa = %p \n " , pa ) ; // Conteúdo inicializado (&a). printf ("pa =% p \ n", pa) / / initialisiert Content (& a). "pb = %p \n " , pb ) ; // Conteúdo inicializado (&b). printf ("sc =% p \ n", bp) / / Content starts (& b). "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa ( 7). printf ("* pa =% d \ n", * pa) / / ap wies von Content (7). "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (42). printf ("* bp =% d \ n", * bp) / / content, auf die bp (42). |
Linien 18.19 respectivamnete deklarieren zwei Integer-und zwei Zeiger auf Integer.
Zeilen 23 bis 26 zeigen die Adressen meiner Variablen. Diese Adressen wurden durch das Betriebssystem gegeben und während diese Variablen werden dort fixiert. Eine Variable ändert sich nicht-Adresse während der Programmausführung, kann aber von einer Anwendung zur anderen zu wechseln. Wer definiert, was dieser Adresse ist das Betriebssystem zum Zeitpunkt der Ausführung des Programms. Der Compiler weiß nur, dass x Bytes für jede Variable benötigt werden, und der Interpretation (Typ), dass das Programm diesen Raum zu geben.
Zeilen 30 bis 33 zeigen den Inhalt dieser Variablen, die nicht initialisiert wurde. Es ist Müll, der letzte Wert, dass jemand (ich weiß nicht, wer) den Orten setzen im Arbeitsspeicher des Computers und die nun auf meine Variablen gehören.
Beachten Sie, dass es sicher, kommentieren Linien 36 und 37, als sie den Inhalt von PA und PB, die noch nicht initialisiert wurde darauf zuzugreifen. Während dieser Versuch, wird das Programm versuchen, die Werte der zufälligen Junk wie int-Variablen gültige Adressen zu interpretieren. Je nach Compiler verwendet das Betriebssystem und ihr Schicksal kann harmlos sein oder nicht. Sicher ist, dass das Ergebnis dieser Zeilen unberechenbar und bestimmte Quelle von Problemen ist.
In den Zeilen 41 und 42 Zeiger sind mit den Adressen der Integer-Variablen initialisiert a und b. Von dort werden die Drucke sind wiederholt.
Siehe die Adressen der Zeiger sich nicht ändern, was zu erwarten war. Was sind die Inhalte zu ändern. Die Variablen pa und pb erhalten Sie die Adressen von a und b jeweils. Beachten Sie, dass die Inhalte der Hände genau die Adresse Wert der Variablen a und b, die von der OS am Anfang des Programms gegeben wurden. Überprüfen Sie mit dem bisherigen Drucke. Der Inhalt von PA und PB zeigte der gleiche Inhalt von a und b, die noch nicht initialisiert wurde, oder Abfall. Doch im Gegensatz zu den vorherigen Schritt, jetzt die Zeiger auf gültige Adressen (Adressen von a und b) und dass der Inhalt von a und b sind Müll Speicher Zeiger nun Punkt um Variablen, die bereits zugeteilt worden sind.
In den Zeilen 61 und 62 Integer-Variablen mit den Werten 10 und 13 initialisiert, wieder und druckt.
Diesmal coteúdos von a und b sind nicht mehr Müll. Die Werte sind gut bekannt. Beachten Sie, dass es keine Änderung in der Adressierung von Variablen in Bezug auf die vorherigen Schritte, nur die Werte.
Siehe auch, dass nach a und b initialisiert wurden, den Inhalt von PA und PB wies auch automatisch geändert. Dies geschieht, weil pa und pb auf den gleichen Speicherbereich, der über die Variablen PA und PB verwendet. Dies bedeutet, dass die Inhalte an, auf den ein Zeiger kann durch Ändern des Inhalts der ursprünglichen Variablen, die von ihm wies geändert werden. Und schließlich, Linien 81 bis 97 zeigen, dass auch die Umkehrung gilt, dh die Änderung der Inhalte, auf die ein Zeiger, verändert automatisch den Inhalt der ursprünglichen Variablen wies darauf hin, von ihnen.
Es ist einfacher, dieses Denken von Phrasen auf Portugiesisch als Blick auf den Code zu verstehen.
Für den Moment ...
Dies war die grundlegende Operationen mit Zeigern. Es gibt immer noch interessante Dinge zu wie Zeiger auf Funktionen, zum Beispiel zu sehen, aber das ist als ein Thema für Fortgeschrittene. Im Anschluss an diese Serie, die für 4 Beiträge geplant ist, siehe Referenzen, Unterschiede und Gemeinsamkeiten zwischen Zeiger und Referenzen und schließlich Zeiger auf Funktionen.
Links
- ponteiros.zip (alle Quellen der Post);
- 01-declaracao.cpp
- 02-tamanhos.cpp
- 03-utilizando.cpp
- 04-pegadinha.cpp
- 05-enderecos.cpp
- Zeiger auf cplusplus.com
- The Guilty
Kommentare
- http://blog.blabos.org/2009/05/ponteiros-e-referencias-em-c-parte-2/ Zeiger und Referenzen in C + + Teil 2: Blog Blaber von bleb
- http://www.caloni.com.br/blog/archives/ultimas-pesquisas-na-blogosfera-nacional Caloni.com.br »Blog Archive» Neueste Forschungsergebnisse in der nationalen Blogosphäre
- http://blog.blabos.org/2009/05/ponteiros-e-arrays/ Zeiger und Arrays: Blaber Blog von bleb
- Fernando
- Fernando
- http://blabos.pip.verisignlabs.com/ blab
- http://blabos.pip.verisignlabs.com/ blab
- Bruno http://www.brunodanielmarinho.com
- Bruno http://www.brunodanielmarinho.com

