Jak sizeof działa z tym dereferencją wskaźnika do tablicy?

9

Tutaj mam wskaźnik ptrdo tablicy arr4 liczb całkowitych. ptrwskazuje na całą tablicę. ptr[0]lub *ptrwskazuje pierwszy element tablicy, więc dodanie 1 ptr[0]daje adres drugiego elementu tablicy.

Nie rozumiem, dlaczego użycie sizeof(ptr[0])daje rozmiar całej tablicy, 16 bajtów, a nie rozmiar tylko pierwszego elementu, 4 bajty (jak ptr[0]wskazuje na pierwszy element w tablicy).

int arr[4] = {0, 1, 2, 3};
int (*ptr)[4] = &arr;
printf("%zd", sizeof(ptr[0])); //output is 16
Abd-Elrahman Mohamed
źródło
Czy nie powinna być druga linia int *ptr = arr;? To wskazywałoby na początek (pierwszy element) tablicy, który jest równoważny &arr[0].
Andreas Wenzel
1
@AndreasWenzel Czy druga linia nie powinna być int *ptr = arr;? Właściwie nie. int (*ptr)[4]tworzy ptrjako wskaźnik do pełnej tablicy czterech intwartości. Taka składnia wskaźnika jest niezbędna do dynamicznego przydzielania prawdziwych wielowymiarowych tablic. „Tablice 2-wymiarowe” utworzone za pomocą zagnieżdżonych malloc()pętli i błędnie opisane jako tablice wielowymiarowe są tak naprawdę tablicami jednowymiarowymi wskaźników do wielu tablic jednowymiarowych . Zobacz stackoverflow.com/questions/42094465/…
Andrew Henle

Odpowiedzi:

6

OP: ptr[0]wskazuje na pierwszy element w tablicy.

Wpisz zamieszanie. ptr[0]jest tablicą.

ptr jest wskaźnikiem do tablicy 4 int .
ptr[0], podobnie jak *ptrodwołuje wskaźnik do tablicy .
sizeof(ptr[0])to rozmiar tablicy.


Dzięki sizeof(ptr[0]), ptr[0]nie ponieść „wyrażenia typu«»wskaźnik do typu«», który wskazuje na początkowym elementu obiektu Array” nawrócenia. (c11dr §6.3.2.1 3). Z sizeof, ptr[0]jest tablicą.

chux - Przywróć Monikę
źródło
1
@ Abd-ElrahmanMohamed Zgadzam się „Ale ptr [0] [0] jest liczbą całkowitą, która nie wskazuje na liczbę całkowitą”. „ptr [0] to adres pierwszego elementu w tablicy” nie jest prawdą.
chux - Przywróć Monikę
1
@ Abd-ElrahmanMohamed tak, wartości są takie same, ale typy są różne. PTR [0] zawiera rodzaj tablicy i &ptr[0][0]jest int *typu
zielone drzewo
1
@chux ptr[0](domyślnie przekonwertowany na int *) oceniałby adres pierwszego elementu int.
Green Tree
1
@chux about sizeof - prawda, źle zrozumiałem kontekst tego, co powiedziałeś
Green Tree
1
@ Abd-ElrahmanMohamed That not not. printf("someforamt", ptr[0] , ptr[0]+1)robi coś innego niż sizeof(ptr[0]). W ptr[0]pierwszym przypadku następuje niejawna konwersja. Dzięki sizeof(ptr[0]), ptr[0]nie.
chux - Przywróć Monikę
5

ptrtutaj jest typu, pointer to an array of 4 int elementsa typ tablicy ma rozmiar 16 na twojej platformie (sizeof (int) * (liczba elemetns)).

Nie rozumiem, dlaczego użycie sizeof (ptr [0]) daje rozmiar całej tablicy 16 bajtów, a nie tylko pierwszego elementu 4 bajty

ponieważ system typu C ma typy tablic. Tutaj oba arri *ptrma to. Co oświadczasz, że masz. Aby uzyskać sizeof int tutaj powinieneś sizeof (ptr [0] [0]) - gdzie ptr [0] ocenia na tablicę.

Zielone drzewo
źródło
2

z int (*ptr)[4] = &arr ;masz wskaźnik do tablicy czterech liczb całkowitych i wskazujący na arr.

ptrwskazuje teraz arr, jak podwójny wskaźnik. Możemy uzyskać dostęp do elementów arrz użyciem ptr[0][x]gdzie xmoże być 0do 4.

Więc sizeof(ptr[0])to samo cosizeof(arr)

rsonx
źródło
2

Z definicji ptr[0]jest taki sam, jak ten, *(ptr + 0)który z kolei jest taki sam jak *ptr. Ponadto ptrjest inicjowany za pomocą &arr, tak *ptrjest *&arri to jest sprawiedliwe arr. Należy zauważyć, że pośrednie składowanie &arrw ptrsposób nie wykonuje żadnej próchnicy tablicy, więc równoważność jest utrzymywany i bez informacji o typie jest stracone.

Zauważ, że wszystko to jest obliczane w czasie kompilacji, aby uniknąć tej dodatkowej pułapki.

Ulrich Eckhardt
źródło