Pointer
-
Hallo liebe Community,
ich bin noch in der Lernphase und beschäftige mich grade mit Pointern.
Dabei stieß ich auf folgende Unklarheit, welche ich einfach mal in ein Beispiel gepackt habe:printf("Speicheradresse %x enthält %d\n", i, *i); // 1 printf("Speicheradresse %p enthält %d\n", i, *i); // 2 printf("Speicheradresse %p enthält %d\n", i, i[0]); // 3 printf("Speicheradresse %p enthält %d\n", (void *)i, *i); // 4
Die 4 Zeilen geben ja grundsätzlich alle das gleiche aus (bis auf die 1).
Frage zu Zeile 1: Wenn man sich die Ausgabe der 1. Zeile Anschaut, sieht man, dass sie sich gegenüber den anderen unterscheidet. Hier frage ich mich wieso Zeile 1 die Speicheradresse 28ff18 ausgibt, während Zeile 2 usw "0028ff18" ausgeben. (unter Windows)
Unter Linux ist es noch etwas komischer, dort füllt er die "0llen" der Ausgabe von Zeile 2 mit 7ffd.
Was genau passiert da? Was macht der %p formatierer gegenüber dem %x formatierer und wieso werden unter Linux die vorderen Ziffern anders gefüllt?Frage zu Zeile 3:
Hier habe ich den Pointer NICHT Dereferenziert, wieso bekomme ich trotzdem was im Speicher steht? Ich dachte immer, dass die Pointervariable an sich nur die jeweilige Adresse im Speicher enthält. Theo. müsste er dann ja versuchen das [0] element von einer Adresse aufzurufen und einen Error schmeißen. Wieso funktioniert das trotzdem?Frage zu Zeile 4:
Was genau macht das "(void *)" mit dem "i"? Wieso funktioniert das? Macht das überhaupt einen Unterschied. Mir wurde zumindest gesagt, dass von den 4 Zeilen diese die "richtigste" sei.Vielen Dank schonmal.
-
Edit:
Ich gebe nochmal die Ausgabe mit:
Speicheradresse 28ff18 enthält 5
Speicheradresse 0028ff18 enthält 5
Speicheradresse 0028ff18 enthält 5
Speicheradresse 0028ff18 enthält 5Außerdem vergaß ich noch den Pointer für das Beispiel mitzugeben:
int x = 5;
int *i = &x;
-
Zu 1 und 2: %x will einen unsigned int, du übergibst einen Pointer. Was da passiert ist ein Zusammenspiel aus verschiedenen Pointer/Integer Größen, Konvertierungen und UB. Nutze %p für Pointer.
exakt dasselbe wie *(a + x). Wörtlich. Das heißt i[0] ist (i + 0). Es geht aber auch 0[i]!
Zu 4: %p erwartet einen void als Argument, also musst du ihn auch geben. Es wird zwar trotzdem funktionieren, ist aber nicht garantiert.
-
printf
erkennt an den Formatspecifiern (die Zeichen mit dem % davor), was und wie ausgegeben weden soll.printf
holt sich die, zu den Specifiern passende Anzahl, Bytes ab.
Damit da nichts schief läuft, müssen die Parameter auch zu den Specifiern passen.Wie groß (sizeof) ein Pointer bzw ein
int
oderlong
ist hängt von dem System, Compiler, Einstellungen ab.Führende Nullen bei %p:
Damit man Adressen leichter Vergleichen kann, wird bei %p die komplette Adresse ausgegeben. Bbei %x wird eine Zahl ausgegeben. BEi %d wundern dich die fehlenden Nullen ja auch nicht.Zu 7ffd:
Warum solten die Adressen für die Variablen, bei so uterschiedlichen Betriebssystemen, gleich sein?