Was bringt es in C eine Int-Variable mit * als Pointer zu deklarieren?
-
inzane93 schrieb:
Was man mit einem pointer machen kann ist mir schon klar^^
Das las sich ganz anders.
Aber wieso muss man in c dieses sternchen beim deklarieren machen, würde es normalerweise mit
*(normalerIntInDemAdresseSteht)
auch gehen müssen?
Nein, wegen der Typisierung. Der Datentyp bestimmt, was man mit einem Wert alles machen kann, und dereferenzieren kann man nunmal nur Zeiger. Im Vorgänger von C (kreativerweise B genannt) gibt es keine deklarierten Datentypen, da kann man das sogar so machen, aber der Trend geht -- aus m.E. naheliegenden Gründen -- zur starken Typisierung.
-
linux_c89 schrieb:
jede Adresse ist genauso groß wie eine Integervariable
Das wird
a) nicht durch den Standard garantiert und
b) trifft auf einer häufig verwendeten Architektur nicht zu, nämlich I32LP64 - (Integer 32 bit, pointer 64 bit). Beispiel dafür wäre Linux auf x86_64 MaschinenDas kann sein, ich hatte bisher halt nur von "auf 32-bit-Systemen ist eine Integervariable 32 bit groß (Zeiger durch 32-bit implizit genauso) und auf 64-bit-Systemen ist eine Integervariable 64 bit groß genauso wie die Zeiger auf den Systemen" gehört. Dass es durch den Standard nicht gewährleistet ist, habe ich mir klatt gedacht, aber ich habe bisher immer diese Erfahrung gemacht. Na ja, aber wie dein b) ja zeigt, muss es ja auch nicht immer sein
-
[Lagerfeuer]
Im Real-Mode unter MS-DOS war ein int 16 Bit und die Zeiger je nach Speichermodell
16 Bit oder 20 Bit. (als Segment und Offset aufgeteilt in 32 Bit)
[\Lagerfeuer]
-
DirkB schrieb:
[Lagerfeuer]
Im Real-Mode unter MS-DOS war ein int 16 Bit und die Zeiger je nach Speichermodell
16 Bit oder 20 Bit. (als Segment und Offset aufgeteilt in 32 Bit)
[\Lagerfeuer]Besser noch: Zeiger hatten verschiedene Größen, je nachdem, ob Zeiger auf eine Variable oder Zeiger auf eine Funktion.
-
Das hing vom Speichermodell ab, konnte so oder so sein, ob Daten- oder Codezeiger near oder far waren. Und far Zeiger waren natürlich 32 Bit groß, nur die daraus gebildeten Adressen hatten effektiv 20 Bit.
-
Schlimmer noch: Die selbe Speicheradresse hatte auf frühen x86 mehrere äquivalente Bezeichnungen. Umrechnung als 16 * Segment + lokale Adresse, wenn ich das richtig im Kopf habe. D.h.:
0x00001234 ≡ 0x00011224 ≡ 0x00021214 ≡ 0x00031204 ...
Die Adresse war auf zwei Register verteilt - üblicherweise wechselte ein Programm in ein Segment, um dann mit kurzen Zeigern (also nur dem lokalen Adressteil) zu arbeiten. Das führte dazu, dass man immer nur 64k gleichzeitig sehen konnte und sein Sichtfenster nach Bedarf verschieben musste, um Zugriff auf den benötigten Speicher zu kriegen. Es war mitunter ein elendes Gefummel, seine Daten richtig im Speicher anzuordnen.
-
Man sollte mal einen BBCode für alte Gruselgeschichten einfügen.
-
Die Frage, die sich der Themenersteller gestellt hat, habe ich mir heute auch schon gestellt.
Irgendwie habe ich noch keine wirklich praktische Anwendung für Zeiger gefunden.
Bisher erschien es mir so, dass ich, statt
int zahl = 7; int *zeiger = &zahl; if (zeiger == 7)
auch einfach
int zahl = 7; if (zahl == 7)
verwenden könnte. Das erscheint mir bisher sogar noch etwas übersichtlicher als zusätzlich zu einer Variable noch einen zugeordneten Zeiger zu verwenden. Die einzigen Worte, mit denen ich dazu bisher was anfangen kann, sind "ressourcensparend".
-
Dein Codebeispiel testet übrigends ob "zahl" an der Adresse 7 liegt, von daher ist es falsch
Aber ein paar Beispiele wo man Zeiger braucht- Strings
- Call by reference
- Übergeben/zurückgeben von großen Strukturen
- dynamische Speicherverwaltung
- Verkettete Listen, Bäume usw.
Das wäre jetzt das was mir spontan einfällt
in deinem beispiel wäre ein Zeiger natürlich absoluter Quatsch, da hast du recht
-
int zahl = 7; int *zeiger; zeiger = &zahl; // So wird der Zeiger benutzt. if (*zeiger == 7) :warning: ^ dereferenzieren nicht vergessen !
Und du hast sie doch selber schon benutzt bei scanf
-
Im Prinzip braucht man Zeiger, um auf eine Variable indirekt zuzugreifen, weil man auf die Variable selbst keinen Zugriff hat oder sie nicht kennt. Nehmen wir das scanf-Beispiel.
Man schreibt:
int i; scanf("%i", &i);
Aber jetzt sagt Klein-Fritzchen, warum reicht es denn nicht, einfach
scanf("%i");
zu schreiben? scanf könnte doch so implementiert sein, dass es die Eingabe stets in die Variable i schreibt.
Na weil man scanf nicht nur benutzen will, um ints in eine global sichtbare Variable i zu schreiben. Die grundlegenden Prinzipien zur Strukturierung von Programmen verlangen, dass solche Kopplungen aufgelöst werden. Ich muss beim Aufruf scanf sagen, wohin es die Eingabe speichern soll, und scanf muss sich darauf verlassen können, dass es dort, wo ich sage, auch tatsächlich Platz für ein int (oder was auch immer gerade) gibt.
Zeiger sind jetzt genau das Mittel, mit dem ich dieses wohin ausdrücken kann.
Es gibt noch mehr Gründe für Zeiger, z.B. basiert der Zugriff auf Arrayelemente auf Zeigerarithmetik. Speicherverwaltung geht auch nicht ohne.