Hallo,
ich habe eine frage zu einem pointer.
Ich habe zum testen folgenden Code geschrieben
1
inta[12]={1,2,3,4,5,6,7,8,9,10,11,12};
2
3
int*b;
4
printf("adresse b: %p\n",(void*)b);
5
b=&a[4];
6
7
printf("adresse a: %p\n",(void*)a);
8
printf("adresse b: %p\n",(void*)b);
9
printf("adresse a0: %p\n",&a[0]);
10
printf("adresse a4: %p\n",&a[4]);
11
printf("wert a0: %i\n",a[0]);
12
printf("wert a4: %i\n",a[4]);
13
printf("wert b0: %i\n",b[0]);
14
printf("wert b4: %i\n",b[4]);
15
printf("setze a[4] auf 44\n");
16
a[4]=44;
17
printf("wert b0: %i\n",b[0]);
18
printf("groesse a: %u\n",sizeof(a));
19
printf("groesse b: %u\n",sizeof(b));
20
printf("wert b12: %i\n",b[12]);
21
printf("wert a16: %i\n",b[16]);
22
23
return0;
die Ausgabe ist
1
adresse b: 00400080
2
adresse a: 0061FEEC
3
adresse b: 0061FEFC
4
adresse a0: 0061FEEC
5
adresse a4: 0061FEFC
6
wert a0: 1
7
wert a4: 5
8
wert b0: 5
9
wert b4: 9
10
setze a[4] auf 44
11
wert b0: 44
12
groesse a: 48
13
groesse b: 4
14
wert b12: 4198966
15
wert a16: 2
Da habe ich jetzt zwei Fragen zu.
warum sind die Adressen von a[0] und a[4] auch 0061FEEC? Wie bekomme ich
die Adresse von den einzelnen elementen?
Warum ist b[12] ungleich a[16]? dass dort müll drinn steht ist mir klar,
aber sollte nicht bei beiden das selbe drinn stehen? Greifen doch beide
auf die selbe adresse zu?
Jens schrieb:> [...]> Da habe ich jetzt zwei Fragen zu.> warum sind die Adressen von a[0] und a[4] auch 0061FEEC? Wie bekomme ich> die Adresse von den einzelnen elementen?
Die Adressen von a[0] und a[4] sind nicht identisch. Wenn du genau
hinschaust (am besten die HEX Zahlen mal in Kleinbuchstaben schreiben)
siehst du das sie unterschiedlich sind:
[...]
adresse a0: 0061feec
adresse a4: 0061fefc
[...]
Das erste Element des Arrays liegt an der Speicherstelle des Speichers,
der dem Array zugewiesen wurde. Wenn du also "b" auf "a" zeigen lassen
würdest, würde "b" auf das erste Element des Ararys zeigen. Beide
Anweisungen sind also identisch:
1
b=a;
2
b=&a[0];
> Warum ist b[12] ungleich a[16]? dass dort müll drinn steht ist mir klar,> aber sollte nicht bei beiden das selbe drinn stehen? Greifen doch beide> auf die selbe adresse zu?
Vermutlich weil du nicht "a[16]" ausgibst, sondern zweimal "b[12]"
(Tippfehler).
Gruß,
Holger
Jens schrieb:> ("wert b12: %i\n", b[12]);> printf("wert a16: %i\n", b[16])Holger schrieb:>> Warum ist b[12] ungleich a[16]? dass dort müll drinn steht ist mir klar,>> aber sollte nicht bei beiden das selbe drinn stehen? Greifen doch beide>> auf die selbe adresse zu?>> Vermutlich weil du nicht "a[16]" ausgibst, sondern zweimal "b[12]"> (Tippfehler).
Sorry, ich meinte das du zweimal auf den "b"-Zeiger zugreifst (b[12] und
b[16]) anstatt bei der zweiten Ausgabe das Array zu benutzen (a[16]).
Holger schrieb:> [...]> adresse a0: 0061feec> adresse a4: 0061fefc> [...]
Tatsächlich, ist mir nicht aufgefallen. wie kann man es denn klein
printen?
Holger schrieb:> Vermutlich weil du nicht "a[16]" ausgibst, sondern zweimal "b[12]"> (Tippfehler).
Auch hier tatsächlich :). es war ein Tippfehler. wenn ich jetzt steht in
beiden das selbe drinn.
Beseten dank :)
Jens schrieb:> Holger schrieb:>> [...]>> adresse a0: 0061feec>> adresse a4: 0061fefc>> [...]>> Tatsächlich, ist mir nicht aufgefallen. wie kann man es denn klein> printen?
Mir wären keine Optionen für %p bekannt. Da entscheidet der Compiler,
wie die Ausgabe aussieht.
> Holger schrieb:>> Vermutlich weil du nicht "a[16]" ausgibst, sondern zweimal "b[12]">> (Tippfehler).>> Auch hier tatsächlich :). es war ein Tippfehler. wenn ich jetzt steht in> beiden das selbe drinn.
Wobei das nicht zwingend so sein muss. Denn beim Zugriff ausßerhalb des
Arrays kommt nicht nur "müll" raus, sondern das ganze Verhalten ist
undefiniert. Da kann alles passieren, und durch Optimierungen können
ggf. auch recht unerwartete Effekte auftreten. Ein Absturz des Programms
wäre natürlich auch möglich.
Jens schrieb:> Tatsächlich, ist mir nicht aufgefallen. wie kann man es denn klein
Du kannst anstatt %p einfach %x bzw. %X benutzen (im ersten Fall ist die
Ausgabe mit Klein- im zweiten mit Großbuchstaben).
Holger schrieb:> Jens schrieb:>> Tatsächlich, ist mir nicht aufgefallen. wie kann man es denn klein>> Du kannst anstatt %p einfach %x bzw. %X benutzen (im ersten Fall ist die> Ausgabe mit Klein- im zweiten mit Großbuchstaben).
Das hängt dann allerdings vom System ab, ob das passt. %p ist eigentlich
schon das richtige für Zeiger.
Rolf M. schrieb:> Holger schrieb:>> Jens schrieb:>>> Tatsächlich, ist mir nicht aufgefallen. wie kann man es denn klein>>>> Du kannst anstatt %p einfach %x bzw. %X benutzen (im ersten Fall ist die>> Ausgabe mit Klein- im zweiten mit Großbuchstaben).>> Das hängt dann allerdings vom System ab, ob das passt.
Auf 64-Bit-Plattformen mit 32-Bit-int-Typ werden damit die höherwertigen
32 Bit des Pointers bei der Ausgabe abgeschnitten.
> %p ist eigentlich schon das richtige für Zeiger.
Oder alternativ %"PRIxPTR" & Co. Damit kann man zwischen verschiedenen
Darstellungen der Hexzahl wählen:
1
#include<stdio.h>
2
#include<inttypes.h>
3
4
inta[12]={1,2,3,4,5,6,7,8,9,10,11,12};
5
6
intmain(void){
7
printf("%%p -> %p\n",a);// ok
8
printf("%%x -> %x\n",a);// Warnung
9
printf("%%X -> %X\n",a);// Warnung
10
printf("%%\"PRIxPTR\" -> %"PRIxPTR"\n",(uintptr_t)a);// ok
11
printf("%%\"PRIXPTR\" -> %"PRIXPTR"\n",(uintptr_t)a);// ok
12
printf("%%#\"PRIxPTR\" -> %#"PRIxPTR"\n",(uintptr_t)a);// ok
13
printf("%%#\"PRIXPTR\" -> %#"PRIXPTR"\n",(uintptr_t)a);// ok
Yalu X. schrieb:>> Das hängt dann allerdings vom System ab, ob das passt.>> Auf 64-Bit-Plattformen mit 32-Bit-int-Typ werden damit die höherwertigen> 32 Bit des Pointers bei der Ausgabe abgeschnitten.
Oder auch die niederwertigen, je nach Endianness. Und die Anzeige bringt
auch nix mehr, wenn das Zeigerformat etwas komplizierter ist als einfach
nur ein einzelner Hex-Wert. Kommt heut zugegebenermaßen wohl nicht mehr
so oft vor.
Roland schrieb:> Rolf M. schrieb:>> Kommt heut zugegebenermaßen wohl nicht mehr>> so oft vor>> Warum nicht?
Ich würde sagen, weil man in der Regel heute eher mit einem
durchgängigen linearen Adressraum arbeitet und nicht wie z.B. noch unter
DOS mit seiner Unterteilung in Segement- und Offset-Register und sehr
starker Überlappung. Da gab es noch Zeigerwerte, die dann z.B: 1000:A010
heißen. Und 1001:A000 war zwar ein anderer Zeigerwert, der aber auf die
selbe physische Adresse zeigte.
Gaehn... schrieb:> Jens schrieb:>> int *b;>> printf("adresse b: %p\n", (void*)b);>> Wird hier nicht auf den Inhalt der Adresse zugegriffen?
Da wird nicht auf den Inhalt der Adresse zugegriffen.
Das ist ein Cast (Typumwandlung)