Forum: PC-Programmierung Zeiger (Pointer)?


von Nikola Tesla (Gast)


Lesenswert?

Moin zusammen,

Zeiger. Vor allem in C sind sie ja ein oft genutztes Mittel und stehen 
auch charakterisierend für die Vorteile von C. Obwohl ich mich jetzt 
länger damit beschäftige, gibt es immer noch einige Unklarheiten.

Wenn mich z.B. jemand fragt, warum Zeiger denn nun so mächtig sind, kann 
ich weder eine flüssige, noch eine klare Antwort darauf abgeben.

Also, Pointer zeigen auf eine bestimmte Adresse im dynamischen Speicher 
und man kann mit ihnen viel Chaos anstellen - jemand verglich dies mal 
mit dem "Zauberstab" aus Harry Potter. Man kann gutes damit bewirken, 
aber auch viel Unheil anrichten.
Wenn man z.B. mittels eines Pointers auf die Adresse einer deklarierten 
Variablen zeigt und diese ändert, bspw. durch ein Inkrement, dann ändert 
sich ja indirekt die Adresse dieser Variablen.
Damit kann man dann z.B. auf Speicher zugreifen, den man normalerweise 
unangetastet lassen sollte.
Stimmt das soweit? Kann man das ergänzen? Das ist doch nicht alles, 
oder? Weshalb sind Zeiger so ein mächtiger Werkzeug (in C)?

Danke Leute :)

von MaWin (Gast)


Lesenswert?

Hausaufgaben sollten selbst gelöst werden.

von MaWin (Gast)


Lesenswert?

Nikola Tesla schrieb:
> stehen
> auch charakterisierend für die Vorteile von C

Wirklich? Ich denke eher nicht. ;->

Nikola Tesla schrieb:
> Damit kann man dann z.B. auf Speicher zugreifen, den man normalerweise
> unangetastet lassen sollte.

Das ist das Hauptmerkmal von C pointern (und besonders mit cast 
operatoren). ;->

von MaWin (Gast)


Lesenswert?

Nikola Tesla schrieb:
> Vorteile von C

Vorteile gegenüber was?

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

Nikola Tesla schrieb:
> Weshalb sind Zeiger so ein mächtiger Werkzeug (in C)?

Zeiger sind gerne datentechnisch kleiner (z.B. 4 oder 8 Byte) als die 
zugehörigen Datenobjekte auf die der Zeiger zeigt (zum Beispiel ein 
Array oder eine verkettete Liste von ... was auch immer)

Daher ist es günstiger (Rechenleistung, Geschwindigkeit) Zeiger zu 
"bewegen" anstelle echte Datenobjekte. Z.B. 2 Objekte vertauschen:

a = wert x
b = Wert y

Vertausche (a,b) =
  hv := a,
  a  := b,
  b := hv

wenn a, b und hv jeweils ein Zeiger wären, müssten nur 3 x 4 = 12 Bytes 
bewegt werden.
wenn a, b und hv jeweils das echte Datenobjekt (z.B. ein String von 400 
Zeichen) wären, müssten jeweils 3 x 400 = 1200 Bytes bewegt werden. 
(Mithin also die 100-fache Datenmenge welche bewegt wird)

und bei 1 Million derartige Operationen, welche angenommen 1 µ-Sekunde 
pro byte braucht sind das dann ....  (rechne es selber aus)


Die notwendigen Speicherschutz-Mechanismen (damit da nicht auf 
unerlaubte Speicherbereiche zugegriffen werden kann ist halt was 
anderes, und muss halt als "Mehraufwand" berücksichtigt werden.

: Bearbeitet durch User
von MaWin (Gast)


Lesenswert?

Wegstaben V. schrieb:
> Zeiger sind gerne datentechnisch kleiner (z.B. 4 oder 8 Byte) als die
> zugehörigen Datenobjekte auf die der Zeiger zeigt

Das ist aber nicht C spezifisch und gilt generell für pointer.

Wegstaben V. schrieb:
> Die notwendigen Speicherschutz-Mechanismen (damit da nicht auf
> unerlaubte Speicherbereiche zugegriffen werden kann ist halt was
> anderes

un in C nicht bekannt. ;-<

von Heiner (Gast)


Lesenswert?

Nikola Tesla schrieb:
> Zeiger. Vor allem in C sind sie ja ein oft genutztes Mittel und stehen
> auch charakterisierend für die Vorteile von C.

Diese Aussage hat keinen objektiv überprüfbaren Wahrheitsgehalt. Es ist 
eine Meinung, keine Tatsache. Wer sollte das auch entscheiden? Natürlich 
ist das eine perfekte Ausgangsposition für sinnlose Diskussionen ...

Nikola Tesla schrieb:
> Also, Pointer zeigen auf eine bestimmte Adresse im dynamischen Speicher
> und man kann mit ihnen viel Chaos anstellen - jemand verglich dies mal
> mit dem "Zauberstab" aus Harry Potter. Man kann gutes damit bewirken,
> aber auch viel Unheil anrichten.

Das gleiche könnte man über Schraubenzieher, Bügeleisen oder partielle 
Differentialgleichungen sagen. Weißt du, warum das so ist? Weil man mit 
Potters Zauberstab (das muss Code für irgendwas sein ...) so ziemlich 
alles machen kann, daher kann man alles, mit dem man "etwas" machen 
kann, mit dem Zauberstab vergleichen.

Der Vergleich ist sinnlos, weil völlig nichtssagend.

Nikola Tesla schrieb:
> Weshalb sind Zeiger so ein mächtiger Werkzeug (in C)?

Sie entsprechen der Art, wie die Hardware funktioniert. Das erhöht die 
Chance, dass das Programm einigermaßen performant sein wird.

Der ganze Rest ist subjektiv: Vielleicht mag man Zeiger als Konstrukt 
einer Hochsprache, vielleicht mag man sie nicht. Schon die Frage, ob 
Zeiger "mächtig" sind, kann man kontrovers diskutieren: Offensichtlich 
geht es ja auch ohne. Wie mächtig kann das Konzept dann schon sein?

Nikola Tesla schrieb:
> Damit kann man dann z.B. auf Speicher zugreifen, den man normalerweise
> unangetastet lassen sollte.

..., was man sinngemäß auch über Schraubenzieher, Bügeleisen und 
partielle Differentialgleichungen sagen könnte. "Man kann etwas damit 
machen, was man normalerweise nicht machen sollte" trifft mal wieder auf 
praktisch alles zu.

Zeiger sind genau dann gefährlich, wenn es auch so ziemlich alle anderen 
Sprachkonstrukte sind: Wenn sie ungeprüft direkt auf die Hardware 
durchgreifen. Irgendjemand muss also aufpassen, heute ist das regelmäßig 
das Betriebssystem.

Nikola Tesla schrieb:
> Wenn mich z.B. jemand fragt, warum Zeiger denn nun so mächtig sind, kann
> ich weder eine flüssige, noch eine klare Antwort darauf abgeben.

Weniger anschauliche Vergleiche suchen, dafür mehr harte Fakten, klar 
getrennt von Bewertungen und Meinungen. Langweilig, aber wirksam.

von mh (Gast)


Lesenswert?

Nikola Tesla schrieb:
> Weshalb sind Zeiger so ein mächtiger Werkzeug (in C)?

Da kann man so viele verschiedene Antworten drauf geben. Ich wähle mal 
"Weil man ohne Zeiger keine Funktionen aufrufen und keine Arrays 
benutzen kann."

Nikola Tesla schrieb:
> Damit kann man dann z.B. auf Speicher zugreifen, den man normalerweise
> unangetastet lassen sollte.
Dann ist es wahrscheinlich kein C mehr.

von Rolf M. (rmagnus)


Lesenswert?

Nikola Tesla schrieb:
> Also, Pointer zeigen auf eine bestimmte Adresse im dynamischen Speicher

Sie zeigen auf eine bestimmte Speicherstelle. Dazu enthalten sie die 
Adresse dieser Speicherstelle. Ob die im dynamischen Speicher liegt oder 
nicht, ist davon unabhängig. Dynamischer Speicher ist also keine 
Voraussetzung für die Verwendung von Zeigern, aber umgekehert sind 
Zeiger eine Voraussetzung für dynamischen Speicher. Die Adresse eines 
dynamisch allokierten Objekts ergibt sich ja erst zur Laufzeit, daher 
braucht man etwas, wo man diese Adresse speichern und über das man das 
Objekt dann auch nutzen kann.

> Wenn man z.B. mittels eines Pointers auf die Adresse einer deklarierten
> Variablen zeigt und diese ändert, bspw. durch ein Inkrement, dann ändert
> sich ja indirekt die Adresse dieser Variablen.

Nein, die Adresse einer Variablen ist fix und kann nicht geändert 
werden. Der Zeiger zeigt dann einfach nicht mehr auf die Variable.

> Damit kann man dann z.B. auf Speicher zugreifen, den man normalerweise
> unangetastet lassen sollte.

Ob man das kann, sagt C nicht. Es sagt, wenn man es versucht, ist das 
Verhalten des Programms undefiniert.

von PittyJ (Gast)


Lesenswert?

Es gab in vielen Hochsprachen (vor und neben C) das Konzept von 
Pointern. Sobald dynamischer Speicher ins Spiel kommt, braucht man 
einen.
Das war auch schon in den 60ern bei Algol und Simula der Fall. Auch 
Pascal und dessen Nachfolger haben Pointer.
Fehlerhafte Zuweisungen, Zugriffe auf gelöschten Speicher, auch das habe 
ich mit den anderen Sprachen geschafft.

von Dirk B. (dirkb2)


Lesenswert?

Nikola Tesla schrieb:
> Weshalb sind Zeiger so ein mächtiger Werkzeug (in C)?

Weil C die Zeiger offen trägt und nicht hinter irgendwelchen anderen 
Konstrukten versteckt.
Weil C keine anderen Werkzeuge hat.

von A. S. (Gast)


Lesenswert?

Nikola Tesla schrieb:
> Pointer zeigen auf eine bestimmte Adresse im dynamischen Speicher.

Nein. Zwar möglich aber weder zwingend noch überwiegend.

Nikola Tesla schrieb:
> Wenn man z.B. mittels eines Pointers auf die Adresse einer deklarierten
> Variablen zeigt und diese ändert, bspw. durch ein Inkrement, dann ändert
> sich ja indirekt die Adresse dieser Variablen.

Nein. Das ergibt so wenig Sinn, dass man diese Aussage nicht Mal 
korrigieren könnte.

> Damit kann man dann z.B. auf Speicher zugreifen, den man normalerweise
> unangetastet lassen sollte.

Du solltest lieber die Aufgabe Posten oder was Du nicht verstanden hast. 
Oder was Du schon an C kennst.

von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

Nikola Tesla schrieb:
> Pointer zeigen auf eine bestimmte Adresse im dynamischen Speicher

Nö, die können auf jede beliebige Adresse zeigen. Dass kann auch 
Hardware oder anders sein.

Mach dir einfach mal klar wie eine CPU im allgemeinen so funktioniert 
und wie die mit den Adressen umgeht dann wird dir auch klarer was die 
bewirken.
Und wenn du mal versuchst in Asembler zu programieren hantierst du noch 
viel mehr mit Adressen.

Und damit ist auch der Fluch und Segen zugleich von C erklärt, C ist 
halt noch sehr Assember nah und somit CPU nah und erlaubt den direkten 
zugriff auf alle Adressen ohne Netz und doppelten Boden (so feinheiten 
wie Kernel-Mode /User-Mode, MMU usw. moderner CPU-Architekturen mal 
außen vor gelassen).

Sprachen wie z.B. Pascal oder JAva bauen da einfach eine paar Schichten 
Watte drum herum damit der Programierer eben nicht mehr direkt auf die 
Adressen zugreifen kann/muss/darf und wandeln das halt in den 
Zwichenschichten entsprechend um. Aber auch da steht am ende eine 
Addresse mit der die CPU arbeiten kann. Nur der Programierer sieht diese 
nicht mehr so direkt und kann somit einige Fehler weniger machen - aber 
das kostet auch alles Rechenzeit.

von Klaus W. (mfgkw)


Lesenswert?

Nikola Tesla schrieb:
> Wenn man z.B. mittels eines Pointers auf die Adresse einer deklarierten
> Variablen zeigt und diese ändert, bspw. durch ein Inkrement, dann ändert
> sich ja indirekt die Adresse dieser Variablen.

Nein.
Wenn man einen Zeiger ändert, dann ändert man nicht die Adresse einer 
Variablen. Aber der Zeiger zeigt danach nicht mehr auf die Variable, 
sondern daneben.

von Adam P. (adamap)


Angehängte Dateien:

Lesenswert?

Nikola Tesla schrieb:
> Also, Pointer zeigen auf eine bestimmte Adresse im dynamischen Speicher

Im µC Bereich kannst dein Pointer auch auf Flash Adressen zeigen lassen 
oder einfach irgendwo auf eine RAM Adresse...dieser Speicher muss ja 
nicht "dynamisch" mit malloc allokiert sein (falls du das mit dynamisch 
meinst).

Nikola Tesla schrieb:
> Wenn man z.B. mittels eines Pointers auf die Adresse einer deklarierten
> Variablen zeigt und diese ändert, bspw. durch ein Inkrement, dann ändert
> sich ja indirekt die Adresse dieser Variablen.

Das wäre ja schlimm, wenn das so wäre!!!
Was du meinst ist, du kannst den Pointer inkrementieren, dann zeigt er 
auf die nächste Adresse.

Schau mal:
Ausgabe oben im Bild.
1
int main(void)
2
{
3
    uint8_t foo[3] = {1, 2, 3};
4
    uint8_t* p;
5
6
    printf("foo[0] liegt auf Adr.: 0x%08X und hat den Wert: %d\n", &foo[0], foo[0]);
7
    printf("foo[1] liegt auf Adr.: 0x%08X und hat den Wert: %d\n", &foo[1], foo[1]);
8
    printf("foo[2] liegt auf Adr.: 0x%08X und hat den Wert: %d\n\n", &foo[2], foo[2]);
9
10
11
    /* Pointer auf foo[0] zeigen lassen und Wert um 1 erhöhen */
12
    p = &foo[0];
13
    (*p)++;        // Oder:   *p = *p + 1;
14
  
15
    printf("foo[0] liegt auf Adr.: 0x%08X und hat den Wert: %d\n", &foo[0], foo[0]);
16
    printf("foo[1] liegt auf Adr.: 0x%08X und hat den Wert: %d\n", &foo[1], foo[1]);
17
    printf("foo[2] liegt auf Adr.: 0x%08X und hat den Wert: %d\n\n", &foo[2], foo[2]);
18
19
20
    /* Zeiger eine Adresse weiter und Wert auf 0 setzen */
21
    p++;
22
    *p = 0;
23
24
    printf("foo[0] liegt auf Adr.: 0x%08X und hat den Wert: %d\n", &foo[0], foo[0]);
25
    printf("foo[1] liegt auf Adr.: 0x%08X und hat den Wert: %d\n", &foo[1], foo[1]);
26
    printf("foo[2] liegt auf Adr.: 0x%08X und hat den Wert: %d\n\n", &foo[2], foo[2]);
27
28
29
    return 0;
30
}

An deiner Stelle würde ich mir solche kleinen Programme erstellen und 
einfach mal damit "rumspielen" dann erkennst/lernst du am besten, da du 
siehst was passiert.

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Adam P. schrieb:
> printf("foo[0] liegt auf Adr.: 0x%08X und hat den Wert: %d\n", &foo[0],
> foo[0]);

Der Formatspecifier bei printf für einen Pointer ist %p

von Johannes S. (Gast)


Lesenswert?

Ein Zeiger muss nicht mal auf einen gültigen Speicher zeigen. Wenn der 
Adressbereich sehr groß ist, dann liegt nicht überall Speicher oder 
Hardware.

Immerhin sind Zeiger in C typisiert, d.h. wenn ein Zeiger auf ein int 
deklariert wurde, dann meckert der Compiler wenn ich diesem die Adresse 
auf ein float zuweisen möchte. Das kann man erwingen, das gehört aber zu 
den 'gefährlichen' Operationen in C.

Und Zeiger können auch auf Funktionen, also ausführbahren Code zeigen. 
Auch gefährlich, aber sehr praktisch.

von Adam P. (adamap)


Lesenswert?

Dirk B. schrieb:
> Adam P. schrieb:
>> printf("foo[0] liegt auf Adr.: 0x%08X und hat den Wert: %d\n", &foo[0],
>> foo[0]);
>
> Der Formatspecifier bei printf für einen Pointer ist %p

Ja ist mir beim schreiben auch aufgefallen.
Aber wann wurde der eingeführt?

von Nikolaus S. (Firma: Golden Delicious Computers) (hns)


Lesenswert?

Zeiger sind in C das was in Assembler bzw. dem Prozessor Adressregister 
und indirekte Adressierung sind.
In anderen Programmiersprachen versteckt man das komplett hinter 
Variablendeklarationen, Array-Indizierung und vollautomatischer 
Speicherverwaltung, so dass man keinen Unfug damit machen kann.
Der Nachteil anderer höherer Sprachen ist natürlich, dass man überhaupt 
keinen Unfug (= Tricks, wenn man genau weiß was man tut) damit machen 
[i]kann[/i].
Deshalb ist C im Embedded-Bereich und bei Betriebssytemkernels so 
beliebt. Weil man da aus Performancegründen oft mit verschiedenen Tricks 
arbeiten muß, die C eben nicht verbietet.

: Bearbeitet durch User
von mh (Gast)


Lesenswert?

Adam P. schrieb:
> Ja ist mir beim schreiben auch aufgefallen.
> Aber wann wurde der eingeführt?

Steht schon im Anso-C

von Adam P. (adamap)


Lesenswert?

mh schrieb:
> Adam P. schrieb:
>> Ja ist mir beim schreiben auch aufgefallen.
>> Aber wann wurde der eingeführt?
>
> Steht schon im Anso-C

Ja habs grad in C89 gefunden:

"The %p conversion specifier was added to C89 for pointer conversion 
since the size of a pointer is not necessarily the same as the size of 
any integer type.  Because an implementation may support more than one 
size of pointer, the corresponding argument is expected to be a pointer 
to void."

Mh, ist mir noch nie aufgefallen :)

von Dirk B. (dirkb2)


Lesenswert?

Adam P. schrieb:
> Mh, ist mir noch nie aufgefallen :)

size_t kennst du aber.
Auch dass es dafür einen Modifier für printf gibt?
Und den hh Modifier bei scanf?
Und dass %lf bei printf nicht vorgesehen ist (war).

von Adam P. (adamap)


Lesenswert?

Dirk B. schrieb:
> size_t kennst du aber.

Ja klar.

Dirk B. schrieb:
> Auch dass es dafür einen Modifier für printf gibt?
> Und den hh Modifier bei scanf?
> Und dass %lf bei printf nicht vorgesehen ist (war).

Nutze printf und scanf eigentlich nie.

von Rolf M. (rmagnus)


Lesenswert?

Dirk B. schrieb:
> Und dass %lf bei printf nicht vorgesehen ist (war).

Dafür aber %Lf.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.