Адрес указателя, зная начальный адрес - PullRequest
0 голосов
/ 06 июня 2018

У меня есть следующий код:

int main(){
int tab[5]={10, 20, 30, 40, 50};
int *ptr;
ptr=tab+4;
printf("%d,%#x,%#x. \n",*ptr-1,&tab,ptr);
return 0;}

«вкладка» находится в зоне памяти, которая начинается в платье 0x28FEF8.

Я знаю, что значение * ptr-1равен 49, а значение & tab равно 0x28FEF8.

Может кто-нибудь объяснить, почему значение "ptr" равно 0x28FF08?Я предполагал, что это будет 0x28FEFC.

Спасибо заранее!

1 Ответ

0 голосов
/ 06 июня 2018

Если мы «рисуем» ваш массив так, как он расположен в памяти, он будет выглядеть примерно так:

+----+----+----+----+----+
| 10 | 20 | 30 | 40 | 50 |
+----+----+----+----+----+

Тогда вам нужно помнить, что массивы естественным образом распадаются на указатели на их первый элемент, то есть tab равно &tab[0].И затем вам нужно помнить, что для любого массива или указателя a и индекса i выражение a[i] точно равно *(a + i).Из этого легко сделать вывод, что tab + 4 равен &tab[4], то есть указателю на пятый элемент.

Так что, если мы снова нарисуем массив, но теперь с указателями:

+----+----+----+----+----+
| 10 | 20 | 30 | 40 | 50 |
+----+----+----+----+----+
^                   ^
|                   |
&tab[0]             &tab[4]
|
&tab

Если &tab[0] равно 0x28fef8, то &tab[4] равно 0x28fef8 + sizeof(int) * 4, так как оно указывает на индекс 4 массива int, и это действительно 0x28ff08.

Обратите внимание, что хотя &tab[0] и &tab указывают на одно и то же местоположение, они семантически различны.&tab[0] является указателем на отдельные элементы и имеет тип int *, тогда как &tab является указателем на массив и имеет тип int (*)[5].


В связанной заметке,правильный формат для печати void * указателей - "%p".Таким образом, ваша печать должна быть действительно

printf("%d,%p,%p. \n", *ptr-1, (void *) &tab, (void *) ptr);

Обратите внимание, что приведение к void * действительно необходимо.

...