Wie funktioniert sizeof mit dieser Dereferenzierung eines Zeigers auf ein Array?

9

Hier habe ich einen Zeiger ptrauf ein Array arrvon 4 ganzen Zahlen. ptrzeigt auf das gesamte Array. ptr[0]oder *ptrzeigt auf das erste Element des Arrays. Wenn Sie also 1 hinzufügen, erhalten Sie ptr[0]die Adresse des zweiten Elements des Arrays.

Ich kann nicht verstehen, warum using sizeof(ptr[0])die Größe des gesamten Arrays angibt, 16 Bytes, nicht die Größe nur des ersten Elements, 4 Bytes (als ptr[0]Punkte auf das erste Element im Array).

int arr[4] = {0, 1, 2, 3};
int (*ptr)[4] = &arr;
printf("%zd", sizeof(ptr[0])); //output is 16
Abd-Elrahman Mohamed
quelle
Sollte nicht die zweite Zeile sein int *ptr = arr;? Das würde dazu führen, dass es auf den Start (das erste Element) des Arrays zeigt, was äquivalent zu ist &arr[0].
Andreas Wenzel
1
@AndreasWenzel Sollte nicht die zweite Zeile sein int *ptr = arr;? Nicht wirklich. int (*ptr)[4]Erstellt ptrals Zeiger auf ein vollständiges Array von vier intWerten. Eine solche Zeigersyntax ist erforderlich, um echte mehrdimensionale Arrays dynamisch zuzuweisen. Die "zweidimensionalen Arrays", die mit verschachtelten malloc()Schleifen erstellt und fälschlicherweise als mehrdimensionale Arrays beschrieben werden, sind tatsächlich 1-d-Arrays von Zeigern auf mehrere 1-d-Arrays. Siehe stackoverflow.com/questions/42094465/…
Andrew Henle

Antworten:

6

OP: ptr[0]zeigt auf das erste Element im Array.

Typ Verwirrung. ptr[0]ist ein Array.

ptr ist ein Zeiger auf Array 4 von int .
ptr[0], wie *ptrder Zeiger auf ein Array verzögert .
sizeof(ptr[0])ist die Größe eines Arrays.


Mit sizeof(ptr[0]), ptr[0]nicht incur „ein Ausdruck mit Typ‚‘Zeiger auf Typen‚‘ , dass die Punkte auf das Anfangselement der Arrays Objekt“ Konvertierung. (c11dr §6.3.2.1 3). Mit sizeof, ptr[0]ist ein Array.

chux - Monica wieder einsetzen
quelle
1
@ Abd-ElrahmanMohamed Zustimmen "Aber ptr [0] [0] ist eine ganze Zahl, die nicht auf eine ganze Zahl zeigt". "ptr [0] ist die Adresse des ersten Elements im Array" ist nicht wahr.
chux
1
@ Abd-ElrahmanMohamed ja, die Werte sind gleich, aber die Typen sind unterschiedlich. ptr [0] hat Array-Typ und &ptr[0][0]hat int *Typ
Green Tree
1
@chux ptr[0](implizit konvertiert in int *) würde die Adresse des ersten int-Elements auswerten.
Grüner Baum
1
@chux über sizeof - richtig, ich habe den Kontext von dem, was Sie gesagt haben, falsch verstanden
Green Tree
1
@ Abd-ElrahmanMohamed Das geht nicht. printf("someforamt", ptr[0] , ptr[0]+1)macht etwas anderes als sizeof(ptr[0]). Das ptr[0]durchläuft im ersten Fall eine implizite Konvertierung. Mit sizeof(ptr[0]), ptr[0]nicht.
chux
5

ptrHier ist vom Typ pointer to an array of 4 int elementsund der Array-Typ hat auf Ihrer Plattform die Größe 16 (sizeof (int) * (Anzahl der Elemente)).

Ich kann nicht verstehen, warum die Verwendung von sizeof (ptr [0]) die Größe des gesamten Arrays 16 Bytes ergibt, nicht die Größe nur des ersten Elements 4 Bytes

weil das System vom Typ C Array-Typen hat. Hier beides arrund *ptrhat es. Was Sie erklären, dass Sie haben. Um hier sizeof int zu erhalten, sollten Sie sizeof (ptr [0] [0]) verwenden - wobei ptr [0] als Array ausgewertet wird.

Grüner Baum
quelle
2

mit haben int (*ptr)[4] = &arr ;Sie einen Zeiger auf ein Array von vier ganzen Zahlen und zeigen auf arr.

ptrzeigt jetzt auf arr, wie ein Doppelzeiger. Wir können Elemente zugreifen arrverwenden , ptr[0][x]wo xsein könnte 0zu 4.

So sizeof(ptr[0])ist das gleiche wiesizeof(arr)

rsonx
quelle
2

Per Definition ptr[0]ist das gleiche wie*(ptr + 0) was wiederum dasselbe ist wie *ptr. Weiter ptrwird mit initialisiert &arr, so *ptrist *&arrund das ist gerecht arr. Man beachte , dass die Zwischenspeicherung von &arrin ptrsich nicht jeden Array Zerfall durchführt, so dass die Äquivalenz aufrechterhalten wird und keine Typinformationen verloren.

Beachten Sie, dass dies alles zur Kompilierungszeit berechnet wird, um diese zusätzliche Gefahr zu vermeiden.

Ulrich Eckhardt
quelle