Почему указатель ведет себя так в C++
Я нашел эту программу в конкурсном вопросном листе:
#include <iostream>
void main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int*)(&a + 1);
printf("%d %d ",*(a + 1), *(ptr - 1));
}
Выход 2 5
теперь, когда я меняю 5-ю строку на int *ptr=(int*)(&a);
а также printf("%d %d ",*(a + 1), *(ptr));
Выход становится 2 1
В первом случае ptr
получил последний адрес array+1
а во втором случае ptr
получил тот же адрес массива (адрес a
).
Я сомневаюсь, почему это назначение показывает другой тип поведения, когда а увеличивается и назначается ptr
и когда a
назначен на ptr
без приращения?
3 ответа
Когда вы берете адрес массива, вы получаете указатель на массив из 5 дюймов (то есть int(*)[5]
). Когда вы увеличиваете этот указатель, он перемещается на размер массива 5 дюймов. Таким образом, он указывает на следующий массив в последовательности массивов (если у вас действительно была последовательность массивов). Затем, когда вы конвертируете этот указатель в int*
становится указателем на первый int
второго (несуществующего) массива, который является одним элементом после последнего элемента первого массива. Вот что происходит с вашим первым примером.
Во втором примере вы не увеличиваете указатель на массив, поэтому при преобразовании его в int*
становится указателем на первый int
в массиве.
&a
указатель на целочисленный массив размером 5, а ptr
является int*
, Таким образом, &a + 1
увеличение на размер int[5]
, а указатель арифметический на int*
изменяет значение указателя на кратные sizeof(int)
, Таким образом, &a + 1
указывает на адрес, который 5*sizeof(int)
с адреса a
, Кастинг это к int* ptr
и делать ptr-1
дает вам адрес a[4]
,
&a + 1;
Здесь просто a
ссылается на базовый адрес массива, то есть адрес первого элемента. Когда ты сказал a+1
Компилятор увидит +1
применительно к pointer to an int
, Таким образом, он будет увеличиваться на смещение, что заставит его перейти к следующему целому числу.
Тем не менее, когда вы говорите, &a
, это означает адрес этого элемента массива (который имеет тип int [5]
). Таким образом, добавление единицы к нему означает, что следующее смещение будет следующим массивом этого типа, то есть косвенно до конца одного массива. Получение адреса элемента one-past-array не проблема, пока вы не разыграете его.