#include<stdio.h>
int main(void){
int *ptr,a,b;
a = ptr;
b = ptr + 1;
printf("the vale of a,b is %x and %x respectively",a,b);
int c,d;
c = 0xff;
d = c + 1;
printf("the value of c d are %x and %x respectively",c,d);
return 0;
}
der Ausgangswert ist
the vale of a,b is 57550c90 and 57550c94 respectively
the value of c d are ff and 100 respectively%
es stellt sich heraus das ptr + 1 tatsächlich, warum es sich so verhält?
Siehe meine vorherige Antwort auf eine Frage wie diese.
– Jonathon Reinhart
22. Juli 2012 um 7:14 Uhr
Du solltest benutzen %p in printf Formatstrings für Zeiger. Nicht verwenden %x dafür ist es nicht portabel (weil Zeiger und int-s kann eine andere Bitbreite haben).
– Basile Starynkevitch
22. Juli 2012 um 8:12 Uhr
Sie sollten wirklich alle Warnungen für Ihren Compiler aktivieren, z -Wall wenn mit kompilieren gcc; Ihr Code enthält mehrere Fehler! Im Speziellen ptr bleibt nicht initialisiert, wird aber verwendet (undefiniertes Verhalten).
– Basile Starynkevitch
22. Juli 2012 um 8:20 Uhr
@BasileStarynkevitch Ja, du hast recht. Ich überprüfe nur die %xund ‘%p’ gibt es einen Unterschied. Und für den Clang-Compiler kann es auch verwendet werden -Wall Warnung aktivieren?
– mko
22. Juli 2012 um 8:28 Uhr
Weil Zeiger so konzipiert sind, dass sie mit Arrays kompatibel sind:
*(pointer + offset)
ist äquivalent zu
pointer[offset]
Zeigerarithmetik funktioniert also nicht in Bezug auf Bytes, sondern in Bezug auf sizeof(pointer base type)-Bytes große Blöcke.
für 64-Bit-Maschinen kann es bis zu 8 Bytes groß sein.
– Nachnix
22. Juli 2012 um 7:10 Uhr
@Aftnix ja, aber was ist das Problem daran?
– Benutzer529758
22. Juli 2012 um 7:11 Uhr
ein Zeiger ist groß genug, um eine Speicheradresse der Plattform aufzunehmen. Wenn Sie 8 Bytes benötigen, um die Speicheradresse zu speichern, sind es 8 Bytes, unabhängig davon, worauf es zeigt. Ich sage nur, dass Sie der Allgemeinheit halber in Ihrer Antwort darauf hinweisen sollten. An Ihrer Antwort ist nichts auszusetzen, aber die Zeigerarithmetik ist sinnvoll, wenn Sie eine Zeigervariable mit “fester” Größe haben. Ich sage nur, bevor Sie das Prinzip der Zeigerarithmetik erläutern, sollten Sie sagen, dass jede Plattform eine native feste Zeigergröße hat. Aus diesem Grund ist die Zeigerarithmetik auf verschiedenen Plattformen konsistent.
– Nachnix
22. Juli 2012 um 7:20 Uhr
+1, um mich über die Verbindung zwischen Array und Zeiger zu informieren. aber ich kann Ihren Code nicht zum Laufen bringen: printf(“%p”,ptr[1])
– mko
22. Juli 2012 um 8:22 Uhr
eh nicht, printf(“%p”, ptr + 1). Beachten Sie, dass *(ptr + offset) ist äquivalent zu ptr[offset]aber ptr + offset selbst ist nicht!
– Benutzer529758
22. Juli 2012 um 10:04 Uhr
Jewgeni Simkin
Überlegen Sie, was ein Zeiger ist … es ist eine Speicheradresse. Jedes Byte im Speicher hat eine Adresse. Wenn Sie also eine haben int das sind 4 Bytes und seine Adresse ist 1000, 1001 ist eigentlich das 2. Byte davon int und 1002 ist das dritte Byte und 1003 ist das vierte. Da die Größe eines int von Compiler zu Compiler variieren kann, ist es zwingend erforderlich, dass Sie beim Erhöhen Ihres Zeigers nicht die Adresse eines Mittelpunkts in der erhalten int. Die Aufgabe, basierend auf Ihrem Datentyp herauszufinden, wie viele Bytes zu überspringen sind, wird also für Sie erledigt, und Sie können einfach den Wert verwenden, den Sie erhalten, und sich nicht darum kümmern.
Wie Basile Starynkvitch betont, variiert dieser Betrag je nach dem sizeof Eigenschaft des Datenelements, auf das gezeigt wird. Es ist sehr leicht zu vergessen, dass, obwohl Adressen sequenziell sind, die Zeiger Ihrer Objekte den tatsächlichen Speicherplatz berücksichtigen müssen, der zum Unterbringen dieser Objekte erforderlich ist.
Basile Starynkevitch
Zeigerarithmetik ist ein heikles Thema. Eine Zeigeraddition bedeutet den Übergang zu einem nächsten Element, auf das gezeigt wird. Die Adresse wird also um den inkrementiert sizeof das spitze Element.
OMGtechy
Kurze Antwort
Die Adresse des Pointers wird um inkrementiert sizeof(T) wo T ist der Typ, auf den gezeigt wird. Also für ein intwird der Zeiger um inkrementiert sizeof(int).
Wieso den?
Nun, in erster Linie verlangt es die Norm. Der Grund, warum dieses Verhalten nützlich ist (abgesehen von der Kompatibilität mit C), liegt darin, dass Sie eine Datenstruktur haben, die zusammenhängenden Speicher verwendet, wie ein Array oder eine std::vector, können Sie zum nächsten Element im Array wechseln, indem Sie einfach eins zum Zeiger hinzufügen. Wenn Sie zum n-ten Element im Container wechseln möchten, fügen Sie einfach n hinzu.
Schreiben können firstAddress + 2 ist viel einfacher als firstAddress + (sizeof(T) * 2)und hilft, Fehler zu vermeiden, die durch die Annahme von Entwicklern entstehen sizeof(int) ist 4 (möglicherweise nicht) und schreibt Code wie firstAddress + (4 * 2).
In der Tat, wenn Sie sagen myArray[4]du sagst myArray + 4. Aus diesem Grund beginnen Array-Indizes bei 0; Sie addieren einfach 0, um das erste Element zu erhalten (dh myArray zeigt auf das erste Element des Arrays) und n, um das n-te zu erhalten.
Was ist, wenn ich jeweils ein Byte verschieben möchte?
sizeof(char) ist garantiert ein Byte groß, sodass Sie a verwenden können char* wenn Sie wirklich ein Byte auf einmal verschieben möchten.
Ein Zeiger wird verwendet, um auf ein bestimmtes Speicherbyte zu zeigen, das markiert, wo ein Objekt zugewiesen wurde (technisch gesehen kann er überall hin zeigen, aber so wird er verwendet). Wenn Sie Zeigerarithmetik durchführen, arbeitet sie basierend auf der Größe der Objekte, auf die gezeigt wird. In Ihrem Fall ist es ein Zeiger auf ganze Zahlen, die jeweils eine Größe von 4 Bytes haben.
md5
Betrachten wir einen Zeiger p. Der Ausdruck p+n ist wie (unsigned char *)p + n * sizeof *p (Weil sizeof(unsigned char) == 1). Versuche dies :
#include <stdio.h>
#define N 3
int
main(void)
{
int i;
int *p = &i;
printf("%p\n", (void *)p);
printf("%p\n", (void *)(p + N));
printf("%p\n", (void *)((unsigned char *)p + N * sizeof *p));
return 0;
}
13864000cookie-checkWarum ein Zeiger + 1 eigentlich 4 addiertyes
Siehe meine vorherige Antwort auf eine Frage wie diese.
– Jonathon Reinhart
22. Juli 2012 um 7:14 Uhr
Du solltest benutzen
%p
inprintf
Formatstrings für Zeiger. Nicht verwenden%x
dafür ist es nicht portabel (weil Zeiger undint
-s kann eine andere Bitbreite haben).– Basile Starynkevitch
22. Juli 2012 um 8:12 Uhr
Sie sollten wirklich alle Warnungen für Ihren Compiler aktivieren, z
-Wall
wenn mit kompilierengcc
; Ihr Code enthält mehrere Fehler! Im Speziellenptr
bleibt nicht initialisiert, wird aber verwendet (undefiniertes Verhalten).– Basile Starynkevitch
22. Juli 2012 um 8:20 Uhr
@BasileStarynkevitch Ja, du hast recht. Ich überprüfe nur die
%x
und ‘%p’ gibt es einen Unterschied. Und für den Clang-Compiler kann es auch verwendet werden-Wall
Warnung aktivieren?– mko
22. Juli 2012 um 8:28 Uhr