Zeiger und Referenzen in C + + Teil 1

19. April 2009 · in C Geschrieben / C + +

Zeiger und Referenzen sind zwei wichtige Konzepte der Informatik. Sie erscheinen in vielen Programmiersprachen mit einem Kleid oder ein wenig anders, aber im Grunde der Behandlung ist die gleiche. In C + +, mit Zeigern Fähigkeiten wichtig sind.

Pointer ist eine spezielle Art der Daten, Variablen, deren erklärtes Ziel dieser Art können (oder nicht), einige andere Daten im Speicher. Eine Variable vom Typ Zeiger enthält die Adresse einer anderen Sache in Erinnerung. Dieses Ding kann eine Variable, eine Konstante, die zu Beginn eines Datensatzes, eine Funktion, unter anderem.

Zeiger deklarieren

Die Erklärung eines Zeigers ist in der Regel durch Hinzufügen eines * vor dem Variablennamen getan. Eine Notation verwendet viel der Leim * Namen von der Art zu sagen, symbolisch, dass ein "Zeiger erklärt reicht es," anstelle eines "Zeiger-Variable", aber sie sind gleichwertig. Zum Beispiel:

  / / Zeiger auf ein int.
 ptr_num1 ; int * ptr_num1;

 / / Oder so.
 ptr_num2 ; int * ptr_num2;

 / / Zeiger in einen Doppelpfeil.
 ptr_double1 ; double * ptr_double1;

 / / Oder so.
 ptr_double2 ; double * ptr_double2; 

Einmal angemeldet, kann die Zeiger ist, wird die Größe und erfolgt daher in der Erinnerung. Die Größe eines Zeigers ist in der Regel gleich der Anzahl der Bits der Maschine / Anlage in Frage, z. B. 4 Byte in einem 32-Bit.

  17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
  pc ; char c, * pc;
 pi ; int i, * pi;
 pd ; double d * pd;

 / / Der sizeof-Operator, sagt die Größe der Typ des Arguments zurück.
 "Size of char:    " << sizeof ( c ) << " bytes" << endl ; cout << "Size of char:" <<sizeof (c) << "Bytes" <<endl;
 "Size of int:     " << sizeof ( i ) << " bytes" << endl ; cout << "Size of int:" <<sizeof (i) << "Bytes" <<endl;
 "Size of double:  " << sizeof ( d ) << " bytes" << endl ; cout << "Size of double:" <<sizeof (d) << "Bytes" <<endl;

 endl ; cout <<endl;

 "Size of char*:   " << sizeof ( pc ) << " bytes" << endl ; cout << "Größe von char *:" <<sizeof (pc) << "Bytes" <<endl;
 "Size of int*:    " << sizeof ( pi ) << " bytes" << endl ; cout << "Größe von int *:" <<sizeof (pi) << "Bytes" <<endl;
 "Size of double*: " << sizeof ( pd ) << " bytes" << endl ; cout << "Size of double *" <<sizeof (pd) << "Bytes" <<endl; 

Hilfe von Zeigern

Nach seiner Aussage ist der Inhalt eines Zeigers auf einen zufälligen Wert, Abfall der Erinnerung, wie jede Variable. Denn es nützlich zu sein, müssen wir ihm etwas geben. Da ein Zeiger eine Speicheradresse hält, weisen wir 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 ; px = & x;
 y ; & Py = y;

 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) vor dem Namen einer Variablen bedeutet "Adresse", weil sein Name ist "Adresse".

Was ist der Gleichheit verlassen hat, um in der Lage, genau die gleiche Art, dass die andere Seite der Gleichheit ist zu halten. Ein Zeiger speichert eine Adresse. Also an eine Adresse, um einen Zeiger zuweisen, in diesem Fall, müssen Sie eine Adresse mit dem Operator &.

Außer in den Fällen, in denen es implizite Typkonvertierung (z. B. zwischen numerischen Typen), weisen eine Variable, die etwas mit einer anderen Art von deren Ursachen ein Kompilierungsfehler. Zum Glück!

Nach einem Zeiger muss auf eine gültige Adresse Punkt, können wir die Inhalte dieser Adresse mit dem Operator * (Stern Zugang), deren offizieller Name ist "Betreiber de-reference.

Beachten Sie, dass der Stern in einer Erklärung "die Zeiger auf den Typ" im Zusammenhang mit Lesen oder Schreiben der Inhalt eines Zeigers, bedeutet "der Inhalt der Adresse" oder "den Inhalt von spitz." Auch darauf achten, nicht mit dem Symbol für Produkt-Arithmetik zu verwechseln. Um Verwirrung zu vermeiden, denken Sie daran, dass große Tabelle der Vorrang der Operatoren, die Sie übergeben nur die Augen und fiel in Vergessenheit. Hier finden Sie, dass der Betreiber-reference Vorrang vor der Multiplikation Betreiber. Sobald das erledigt ist Sie werden sich erinnern, dass der Betreiber der Verwendungsnachweis 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 ; pb = & b;

 pa * * pb ; c = pa * * * pb;
 pa * * pb ; c = pa * * * pb;
 pa * * pb ; c = pa * * * pb;
 pa ** pb ; c = * pa ** bp;
 * pa ) * ( * pb ) ; c = (* pa) * (* pb);

 "Valor da Pegadinha: " << c << endl ; cout << "Value Wissenswertes:" <<c <<endl; 

Also, wenn die Beweise von Algorithmen Sie fragen, was macht eine der letzten 5 Zeilen des Beispiels werden Sie sagen, dass sie die Inhalte, auf den PA und PB multipliziert. Es wird zu holen, weil dieser PD! Und gegen das im wirklichen Leben, wenn du das wirklich tun müssen, finden Sie Ihren 4 vergangener Generationen zu retten und die Zukunft der 5 Exkommunikation, wenn Sie die letzte Zeile verwenden möchten.

Alles, was man mit einem gemeinsamen Variable können Sie mit dem Inhalt tun, um durch einen Zeiger darauf, entweder lesen oder zu schreiben (es sei denn, es ist klar, dass der Zeiger const ist, aber das ist eine andere rant ...).'s

Adressen und Zeiger

Nehmen Sie zum Beispiel den folgenden 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 der Zuordnung: \ n");

 "&a  = %p \n " , & a ) ; // Endereço válido dado pelo SO. printf ( "& a =% p \ n", & a) / / Gültig-Adresse angegeben, die vom Betriebssystem.
 "&b  = %p \n " , & b ) ; // Endereço válido dado pelo SO. printf ( "& b =% p \ n", & b) / / Gültig-Adresse angegeben, die vom Betriebssystem.
 "&pa = %p \n " , & pa ) ; // Endereço válido dado pelo SO. printf ( "& pa =% p \ n", & pa); / / Gültig-Adresse angegeben, die vom Betriebssystem.
 "&pb = %p \n " , & pb ) ; // Endereço válido dado pelo SO. printf ( "& pb =% p \ n", & pb); / / Gültig-Adresse angegeben, die vom Betriebssystem.

 " \n " ) ; printf ( "\ n");

 "a   = %d \n " , a ) ; // Conteúdo não inicializado (aleatório). printf ( "a =% d \ n", a); / / Inhalt initialisierten (zufällig).
 "b   = %d \n " , b ) ; // Conteúdo não inicializado (aleatório). printf ( "b =% d \ n", b) / / Content initialisierten (zufällig).
 "pa  = %p \n " , pa ) ; // Conteúdo não inicializado (aleatório). printf ( "pa =% p \ n", pa) / / Content initialisierten (zufällig).
 "pb  = %p \n " , pb ) ; // Conteúdo não inicializado (aleatório). printf ( "bp =% p \ n", pb); / / Inhalt initialisierten (zufällig).

 / / Bitte entfernen Sie die folgenden Zeilen ein, kompilieren und ausführen.
 / / Printf ( "* pa =% d \ n", * pa) / / Was wird (random *)?
 / / Printf ( "* pb =% d \ n", * pb); / / Was ist (random *)?

 " \n Após as inicializações dos ponteiros: \n " ) ; printf ( "\ n Nach der Initialisierung von Zeigern: \ n");

 a ; pa = & a;
 b ; pb = & b;

 "&a  = %p \n " , & a ) ; // Mesmo endereço válido dado pelo SO. printf ( "& a =% p \ n", & a); / / Selbst gültige Email-Adresse gegeben, die vom Betriebssystem.
 "&b  = %p \n " , & b ) ; // Mesmo endereço válido dado pelo SO. printf ( "& b =% p \ n", & b) / / Selbst gültige Email-Adresse gegeben, die vom Betriebssystem.
 "&pa = %p \n " , & pa ) ; // Mesmo endereço válido dado pelo SO. printf ( "& pa =% p \ n", & pa); / / Selbst gültige Email-Adresse, die vom Betriebssystem angegeben.
 "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ( "& pb =% p \ n", & pb); / / Selbst gültige Email-Adresse, die vom Betriebssystem angegeben.

 " \n " ) ; printf ( "\ n");

 "a   = %d \n " , a ) ; // Conteúdo não inicializado (aleatório). printf ( "a =% d \ n", a); / / Inhalt initialisierten (zufällig).
 "b   = %d \n " , b ) ; // Conteúdo não inicializado (aleatório). printf ( "b =% d \ n", b) / / Content initialisierten (zufällig).
 "pa  = %p \n " , pa ) ; // Conteúdo inicializado (&a). printf ( "pa =% p \ n", pa) / / initialisiert Inhalt (& a).
 "pb  = %p \n " , pb ) ; // Conteúdo inicializado (&b). printf ( "bp =% p \ n", pb); / / Inhalt initialisiert (b).

 "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa (*pa == a). printf ( "* pa =% d \ n", * pa); / / Inhalt ernannt pa (pa == * a).
 "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (*pb == b). printf ( "* pb =% d \ n", * pb); / / content von pb hingewiesen (* pb == 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); / / Selbst gültige Email-Adresse gegeben, die vom Betriebssystem.
 "&b  = %p \n " , & b ) ; // Mesmo endereço válido dado pelo SO. printf ( "& b =% p \ n", & b) / / Selbst gültige Email-Adresse gegeben, die vom Betriebssystem.
 "&pa = %p \n " , & pa ) ; // Mesmo endereço válido dado pelo SO. printf ( "& pa =% p \ n", & pa); / / Selbst gültige Email-Adresse, die vom Betriebssystem angegeben.
 "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ( "& pb =% p \ n", & pb); / / Selbst gültige Email-Adresse, die vom Betriebssystem angegeben.

 " \n " ) ; printf ( "\ n");

 "a   = %d \n " , a ) ; // Conteúdo inicializado (10). printf ( "a =% d \ n", a); / / Inhalt Stiefel (10).
 "b   = %d \n " , b ) ; // Conteúdo inicializado (13). printf ( "b =% d \ n", b) / / Content Stiefel (13).
 "pa  = %p \n " , pa ) ; // Conteúdo inicializado (&a). printf ( "pa =% p \ n", pa) / / initialisiert Inhalt (& a).
 "pb  = %p \n " , pb ) ; // Conteúdo inicializado (&b). printf ( "bp =% p \ n", pb); / / Inhalt initialisiert (b).

 "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa (*pa == a == 10). printf ( "* pa =% d \ n", * pa); / / Inhalt ernannt pa (* pa == a == 10).
 "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (*pb == b == 13). printf ( "* pb =% d \ n", * pb); / / content von pb hingewiesen (* pb == b == 13).

 " \n Alterando os valores através dos ponteiros: \n " ) ; printf ( "\ n Ändern der Werte über Zeiger: \ n");

 7 ; * Pa = 7;
 42 ; * Pb = 42;

 "&a  = %p \n " , & a ) ; // Mesmo endereço válido dado pelo SO. printf ( "& a =% p \ n", & a); / / Selbst gültige Email-Adresse gegeben, die vom Betriebssystem.
 "&b  = %p \n " , & b ) ; // Mesmo endereço válido dado pelo SO. printf ( "& b =% p \ n", & b) / / Selbst gültige Email-Adresse gegeben, die vom Betriebssystem.
 "&pa = %p \n " , & pa ) ; // Mesmo endereço válido dado pelo SO. printf ( "& pa =% p \ n", & pa); / / Selbst gültige Email-Adresse, die vom Betriebssystem angegeben.
 "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ( "& pb =% p \ n", & pb); / / Selbst gültige Email-Adresse, die vom Betriebssystem angegeben.

 " \n " ) ; printf ( "\ n");

 "a   = %d \n " , a ) ; // Conteúdo inicializado (a == *pa ==  7). printf ( "a =% d \ n", a); / / Inhalt Start (a == * pa == 7).
 "b   = %d \n " , b ) ; // Conteúdo inicializado (b == *pb == 42). printf ( "b =% d \ n", b) / / Inhalt initialisiert (b == * pb == 42).
 "pa  = %p \n " , pa ) ; // Conteúdo inicializado (&a). printf ( "pa =% p \ n", pa) / / initialisiert Inhalt (& a).
 "pb  = %p \n " , pb ) ; // Conteúdo inicializado (&b). printf ( "bp =% p \ n", pb); / / Inhalt initialisiert (b).

 "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa ( 7). printf ( "* pa =% d \ n", * pa); / / Beiträge von pa (7) ernannt.
 "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (42). printf ( "* pb =% d \ n", * pb); / / content, auf den pb (42). 

Die Linie 18 und 19 erklärt respectivamnete zwei und zwei Zeiger auf ganze Zahlen.

Die Zeilen 23 bis 26 zeigt die Adresse meiner Variablen. Diese Adressen wurden durch das Betriebssystem gegeben und sind fix, während die Variablen bestehen. Eine Variable nicht verändert Adresse während des Programms, sondern kann zwischen einer Ausführung und eine weitere Änderung. Wer definiert, was diese Adresse das Betriebssystem zum Zeitpunkt des Programms ist. Der Compiler weiß nur, daß x Bytes für jede Variable benötigt werden, und der Auslegung (Stil), dass das Programm dieser Stelle geben wird.

Zeilen 30 bis 33 zeigen den Inhalt dieser Variablen, die nicht initialisiert wurden. Es ist Müll, der letzte Wert, dass jemand (weiß nicht wer) hat diese Orte im Speicher des Rechners und die gehören jetzt zu meinem Variablen.

Beachten Sie, dass es sicher ist, entfernen Sie den Zeilen 36 und 37, wie sie auf den Inhalt zugreifen wollen, auf den PA und PB, die nicht initialisiert wurde. Bei diesem Versuch wird das Programm versuchen, die Werte der zufällige Zeichen zu interpretieren, als ob sie Adressen von int-Variablen gelten. Abhängig von der Compiler, das Betriebssystem verwendet werden und ihr Schicksal kann harmlos sein oder nicht. Sicher ist, dass das Ergebnis dieser Zeilen nicht vorhersagbar ist und sicherer Quelle von Problemen.

In den Zeilen 41 und 42 die Zeiger sind mit den Adressen der Integer-Variablen initialisiert a und b. Seitdem sind die Ausdrucke wiederholt werden.

Beachten Sie, dass die Adressen der Zeiger sich nicht verändern, was erwartet wurde. Welche Veränderungen sind die Inhalte. Variablen PA und PB erhalten die Adressen von A und B zu. Beachten Sie, dass der Inhalt der Hand genau ist der Wert der Adresse der Variablen a und b, die von der OS zu Beginn des Programms gegeben wurden. Prüfen Sie mit dem Drucke oben. Der Inhalt, auf den PA und PB ist den gleichen Inhalt von a und b, die nicht initialisiert worden ist, dh, Müll. Im Gegensatz zu den vorherigen Schritt, jetzt Zeiger auf gültige Adressen (Adressen von a und b) und dass der Inhalt von a und b sind Müll Speicher Zeiger nun auf Variablen zugewiesen wurden.

In den Zeilen 61 und 62 der Integer-Variablen werden mit den Werten 10 und 13 initialisiert, und die Drucke wiederholte.

Dieses Mal coteúdos von a und b sind nicht mehr Müll. Werte ordnungsgemäß bekannt. Beachten Sie, dass es keine Änderung in der Adressierung der Variablen in Bezug auf die vorherigen Schritte, nur die Werte.

Siehe auch, daß nach a und b initialisiert wurden, wies die Inhalte von PA und PB sich auch automatisch geändert. Dies geschieht, weil PA und PB auf die gleiche Bereiche des Arbeitsspeichers durch die Variablen PA und PB verwendet. Dies bedeutet, dass der Inhalt durch einen Zeiger darauf hingewiesen kann durch Veränderung der Inhalte der ursprünglichen Variablen geändert werden darauf hingewiesen, von ihm. Und schließlich, Zeilen 81 bis 97 zeigen, dass das auch umgekehrt, dh die Änderung der Inhalte durch einen Zeiger zeigt, ändert sich automatisch die Inhalte der ursprünglichen Variablen wies darauf hin, die von ihnen.

Es ist einfacher, diese Gedanken über die Sätze in Portugiesisch als Blick auf den Code zu verstehen.

Für den Moment ...

Dies war die grundlegende Bedienung mit Zeigern. Es gibt immer noch interessante Dinge als Zeiger auf Funktionen gesehen werden, zum Beispiel, aber das ist mehr als ein Thema für Fortgeschrittene. Nach dieser Serie, die für 4 Stellen vorgesehen ist, siehe Referenzen, Unterschiede und Gemeinsamkeiten zwischen Zeiger und Referenzen und schließlich Zeiger auf Funktionen.

Links

Kommentare

5 Responses to "Zeiger und Referenzen in C + + Teil 1"

  1. [...] Mit diesem Versuch einer Reihe von Beiträgen über Zeiger und Referenzen, die sprechen über Zeiger begann, diskutieren heute [...]

  2. [...] [...] Pointeiros und Referenzen

  3. [...] Ersten Beitrag dieser Serie sprechen wir ein wenig über Zeiger. In der zweiten, sprechen wir über Referenzen. Heute werden wir uns auf die enge Beziehung zu konzentrieren (ui!) Zwischen Zeigern und [...]

  4. Fernando am 26. Dezember 2009 18:50

    Dude, hast du mir beibringen, wie man das macht nach den Code wie Sie auf dem Laufenden?
    In einem Feld vor allem durch Kennzeichnung der Leitungen und vor allem die Stichworte der Sprache?

  5. blab am 28. Dezember 2009 08:48

    Kein Problem!

    Die Wordpress hat ein Plugin namens WP-Syntax, die hinter den Kulissen die GeSHi verwendet.

    Nach der Installation können Sie Ihren Code in PRE-Tags setzen, indem die Attribute "Sprache" und "Linie". Die Sprache ist selbsterklärend und hat eine Liste der Sprachen in der Dokumentation und der Zeile ist der Startlinie.

    Die GeSHi kann auch genutzt werden, um diese Funktion in Wikis hinzuzufügen.

    Tipp: Bevor Sie kopieren und fügen Sie den Code, ersetzen Sie alle Tabs durch 4 Leerzeichen. Dadurch wird der Code unabhängig von der Art auf die Registerkarte Anwendung.

    Hugs

Lassen Sie eine Antwort




Powered by WP Hashcash