Як розмірofof працює з цим перенаправленням вказівника на масив?


9

Тут у мене є вказівник ptrна масив arrіз 4 цілих чисел. ptrвказує на весь масив. ptr[0]або *ptrвказує на перший елемент масиву, тому додаючи 1, ptr[0]надає адресу другого елемента масиву.

Я не можу зрозуміти, чому використання sizeof(ptr[0])дає розмір усього масиву, 16 байт, а не розмір лише першого елемента, 4 байти (як ptr[0]вказує на перший елемент масиву).

int arr[4] = {0, 1, 2, 3};
int (*ptr)[4] = &arr;
printf("%zd", sizeof(ptr[0])); //output is 16

Чи не повинен бути другий рядок int *ptr = arr;? Це вказувало б на початок (перший елемент) масиву, який еквівалентний &arr[0].
Андреас Венцель

1
@AndreasWenzel Чи не повинен бути другий рядок int *ptr = arr;? Власне, ні. int (*ptr)[4]створює ptrяк вказівник на повний масив з чотирьох intзначень. Синтаксис вказівника на зразок цього необхідний для динамічного розподілу істинно-багатовимірних масивів. "2-мірні масиви", створені за допомогою вкладених malloc()циклів і неправильно описані як багатовимірні масиви, справді є одновимірними масивами покажчиків на декілька 1-d масивів. Дивіться stackoverflow.com/questions/42094465/…
Ендрю Генле,

Відповіді:


6

OP: ptr[0]вказує на перший елемент масиву.

Тип плутанини. ptr[0]- це масив.

ptr - покажчик масиву 4 int .
ptr[0], як і *ptrвідмінні знаки вказівника на масив .
sizeof(ptr[0])- розмір масиву.


З sizeof(ptr[0]), ptr[0]не несе "вираз з типом" "вказівник на тип", який вказує на початковий елемент об'єкта масиву "перетворення. (c11dr §6.3.2.1 3). З sizeof, ptr[0]є масив.


1
@ Abd-ElrahmanMohamed Погоджуюся "Але ptr [0] [0] - це ціле число, яке не вказує на ціле число". "ptr [0] - адреса першого елемента в масиві" не відповідає дійсності.
chux

1
@ Abd-ElrahmanMohamed так, значення однакові, але типи різні. ptr [0] має тип масиву та &ptr[0][0]має int *тип
Green Tree

1
@chux ptr[0](неявно перетворений в int *) буде оцінювати до адреси першого елемента int.
Зелене дерево

1
@chux про sizeof - правильно, я неправильно зрозумів контекст сказаного вами
Зелене дерево

1
@ Abd-ElrahmanMohamed Це не так. printf("someforamt", ptr[0] , ptr[0]+1)робить щось інше, ніж sizeof(ptr[0]). У ptr[0]першому випадку відбувається інцидентна конверсія. З sizeof(ptr[0]), ptr[0]ні.
chux

5

ptrось тип pointer to an array of 4 int elementsі тип масиву має розмір 16 на вашій платформі (sizeof (int) * (кількість елеметрів)).

Я не можу зрозуміти, чому використання sizeof (ptr [0]) дає розмір усього масиву 16 байт, а не розмір лише першого елемента 4 байти

оскільки система типу C має типи масивів. Ось і те, arrі *ptrє. Що ви заявляєте, що маєте. Щоб отримати sizeof int, вам слід sizeof (ptr [0] [0]) - де ptr [0] оцінює для масиву.


2

у int (*ptr)[4] = &arr ;вас є вказівник на масив із чотирьох цілих чисел та вказівка ​​на arr.

ptrтепер вказує arr, як подвійний вказівник. Ми можемо отримати доступ до елементів з arrдопомогою ptr[0][x]яких xможна було б 0з 4.

Так sizeof(ptr[0])само якsizeof(arr)


2

За визначенням, ptr[0]це те саме, *(ptr + 0)що в свою чергу те саме, що *ptr. Далі ptrініціалізується з &arr, так *ptrє *&arrі це справедливо arr. Зауважимо, що проміжне зберігання&arr в ptrдійсно НЕ виконує ніякого розпаду масиву, так що еквівалентність зберігається і ніякої інформації типу не втрачається.

Зауважте, що все це обчислюється під час компіляції, просто щоб уникнути цього додаткового помилки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.