ich verstehe warum 3 ist die erste Ausgabe (a+1 zeigt auf die zweite Zeile, und wir drucken sie 0th Element.
Meine Frage bezieht sich auf die zweite Ausgabe, dh 2. Meine Vermutung liegt an der Typisierung a wie int *wird das 2D-Array wie ein 1D-Array behandelt und somit a+1 fungiert als Zeiger auf die 2nd Element, und so erhalten wir die Ausgabe als 2.
Sind meine Annahmen richtig oder steckt dahinter eine andere Logik?
Auch ursprünglich, was ist die Art von a wenn es als Zeiger behandelt wird int (*)[2] oder int **?
Die Besetzung hat eine höhere Angemessenheit, sodass Sie ein undefiniertes Verhalten aufrufen, wenn Sie versuchen, zu dereferenzieren a+1.
– Benutzer657267
16. Juli 2014 um 22:35 Uhr
@ user657267 es gibt kein UB
– MM
16. Juli 2014 um 22:58 Uhr
Hoppla, Arrays sind natürlich flach.
– Benutzer657267
16. Juli 2014 um 23:30 Uhr
Notiz: *(a+1)[3] ist nicht dasselbe wie (*(a+1))[3] (es sei denn, die zweite Zahl ist Null, was in Ihrem Code steht)
– Benutzer253751
17. Juli 2014 um 3:47 Uhr
Beachten Sie auch, dass, wenn das “Array” tatsächlich a ist int** (wo die Zeilen des Arrays waren mallocmanuell bearbeitet), obwohl es wie eine aufgerufen werden kann array[x][y]es in ein 1D-Array umzuwandeln und darauf zuzugreifen, wird im besten Fall den Wert von a zurückgeben Zeiger (also Müll aus der Sicht des Anrufers)
– Marco13
17. Juli 2014 um 9:35 Uhr
Vlad aus Moskau
Als Sie Ausdruck geschrieben haben
(int *)a
dann kann das ursprüngliche Array logischerweise auf folgende Weise als eindimensionales Array betrachtet werden
int a[4] = { 1, 2, 3, 4 };
Also Ausdruck a zeigt auf das erste Element gleich 1 dieses imaginären Arrays. Ausdruck ( a + 1 ) zeigt auf das zweite Element des imaginären Arrays gleich 2 und Ausdruck ( a + 1 )[0] gibt den Verweis auf dieses Element zurück, das heißt, Sie erhalten 2.
Welche Beweise haben Sie, dass dies von der Norm vorgeschrieben wird?
– Yakk – Adam Nevraumont
17. Juli 2014 um 2:16 Uhr
hackt
Sind meine Annahmen richtig oder steckt dahinter eine andere Logik?
Ja.
*(a+1)[0] ist äquivalent zu a[1][0]. ((int *)a+1)[0] ist äquivalent zu a[0][1].
Erläuterung:
a zerfällt zum Zeiger auf das erste Element des 2D-Arrays, dh auf die erste Zeile. *a dereferenziert diese Zeile, die ein Array von 2 ist int. Deswegen *a kann als Array-Name der ersten Zeile behandelt werden, der weiter in einen Zeiger auf sein erstes Element zerfällt, dh 1. *a + 1 gibt den Zeiger auf das zweite Element. Dereferenzierung *a + 1 wird geben 1. So:
Beachten Sie, dass a, *a, &a, &a[0] und &a[0][0] alle haben den gleichen Adresswert, obwohl sie unterschiedlichen Typs sind. Nach dem Verfall, a ist vom Typ int (*)[2]. Gießen Sie es zu int * macht nur den Adresswert zu tippen int * und die Arithmetik (int *)a+1 gibt die Adresse des zweiten Elements an.
Was ist ursprünglich der Typ von a, wenn es als Zeiger behandelt wird? (int (*)[2] oder int **?
Es wird typisiert Zeiger auf Array von 2 intdh int (*)[2]
Diese Antwort enthält keine Erklärung dafür, warum dies der Fall ist. Die Gleichwertigkeit geht aus den ausgegebenen Zahlen hervor, bitte begründen Sie diese Gleichwertigkeit. Es beantwortet auch nicht die Frage am Ende des Beitrags.
– Mike Precup
16. Juli 2014 um 22:40 Uhr
In Übereinstimmung mit den Website-Regeln stimme ich basierend auf dem aktuellen Status eines Beitrags ab, nicht wie er möglicherweise sein könnte. Daher habe ich meine Stimme geändert, jetzt da der Beitrag die Frage beantwortet.
– Mike Precup
16. Juli 2014 um 22:45 Uhr
@hackks Es ist, als würde man einem Kunden eine Pizza ungekocht und ohne Belag servieren, „Bestellen!“ schreien und dann sauer werden, wenn er darauf hinweist, dass die servierte Pizza einfach nicht angemessen ist. Abgesehen davon, warum geben Sie überhaupt Antworten mit Versionen? 3 auf der Platte und diese schließen die kleineren aus …
– Utkan Geser
16. Juli 2014 um 23:00 Uhr
@ThoAppelsin – Hast du nie eine deiner Antworten verbessert? Meine Güte. Schauen Sie sich einige der besten Antworten auf SO an, die meisten von ihnen haben mehrere Änderungen. Dieses hier zum Beispiel, 15 Bearbeitungen Es ist nichts falsch an einer Bearbeitung, die die Antwort verbessert.
– ryker
17. Juli 2014 um 0:17 Uhr
@ryyker Ich glaube, was ich gesagt habe, darf nicht aus dem Zusammenhang gerissen werden. hackt sagte gleich bei seinem ersten Kommentar etwas über Geduld; was meiner Meinung nach zu Recht interpretiert wurde “Beurteilen Sie meine Antwort nicht so schnell, sie war damals noch nicht vollständig, ich habe sie noch vorbereitet.”. Natürlich kann man ihre Antwort verbessern, ich auch; Das Problem hier ist, dass er anscheinend die erste Version mit dem Plan gepostet hat, so schnell wie möglich eine Bearbeitung bereitzustellen, was ich nie tue. Widerlegen Sie mich, wenn Sie möchten, es ist unangebracht, eine Antwort voreilig zu posten, wenn Sie wissen, dass sie noch nicht vollständig ist.
– Utkan Geser
17. Juli 2014 um 0:36 Uhr
Ein 2D-Array ist im Wesentlichen ein eindimensionales Array mit einigen zusätzlichen Compiler-Kenntnissen.
Wenn Sie werfen a zu int*entfernen Sie dieses Wissen und es wird wie ein normales eindimensionales Array behandelt (was in Ihrem Fall im Speicher so aussieht 1 2 3 4).
Utkan Geser
Das Wichtigste, was hier zu erkennen ist, ist, dass die a Dort steht der Wert der Adresse, an der sich die erste Zeile befindet. Da das gesamte Array an derselben Stelle beginnt, hat das gesamte Array auch denselben Adresswert; Gleiches gilt für das allererste Element.
Im C Bedingungen:
&a == &a[0];
&a == &a[0][0];
&a[0] == &a[0][0];
// all of these hold true, evaluate into 1
// cast them if you want, looks ugly, but whatever...
&a == (int (*)[2][2]) &a[0];
&a == (int (*)[2][2]) &a[0][0];
&a[0] == (int (*)[2]) &a[0][0];
Aus diesem Grund, wenn Sie die werfen a zu int *wird es einfach 1-zu-1-äquivalent zu &a[0][0] sowohl über den Typ als auch über den Wert. Wenn Sie diese Operationen auf anwenden würden &a[0][0]:
Die Besetzung hat eine höhere Angemessenheit, sodass Sie ein undefiniertes Verhalten aufrufen, wenn Sie versuchen, zu dereferenzieren
a+1
.– Benutzer657267
16. Juli 2014 um 22:35 Uhr
@ user657267 es gibt kein UB
– MM
16. Juli 2014 um 22:58 Uhr
Hoppla, Arrays sind natürlich flach.
– Benutzer657267
16. Juli 2014 um 23:30 Uhr
Notiz:
*(a+1)[3]
ist nicht dasselbe wie(*(a+1))[3]
(es sei denn, die zweite Zahl ist Null, was in Ihrem Code steht)– Benutzer253751
17. Juli 2014 um 3:47 Uhr
Beachten Sie auch, dass, wenn das “Array” tatsächlich a ist
int**
(wo die Zeilen des Arrays warenmalloc
manuell bearbeitet), obwohl es wie eine aufgerufen werden kannarray[x][y]
es in ein 1D-Array umzuwandeln und darauf zuzugreifen, wird im besten Fall den Wert von a zurückgeben Zeiger (also Müll aus der Sicht des Anrufers)– Marco13
17. Juli 2014 um 9:35 Uhr