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 :)
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). ;->
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
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. ;-<
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.
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.
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.
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.
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.
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.
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.
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.
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
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
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.
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?
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
Adam P. schrieb: > Ja ist mir beim schreiben auch aufgefallen. > Aber wann wurde der eingeführt? Steht schon im Anso-C
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 :)
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).
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.