Во-первых, вы сказали: &a
означает адрес a[0]
, поэтому &a+1
должен быть адресом [1]? Нет, вы не правы. &a
означает адрес a
, а не a[0]
. И &a+1
означает, что он увеличивается на размер всего массива , а не только на один размер элементов, а a+1
означает адрес a[1]
.
Здесь
int a[5] = {1,2,3,4,5};
допустим, что базовый адрес a
равен 0x100
--------------------------------------
| 1 | 2 | 3 | 4 | 5 |
--------------------------------------
0x100 0x104 0x108 0x112 0x116 ..
LSB
|
a
Когда вы делаете
int *ptr = (int*)(&a+1);
Где ptr
баллов? первый (&a+1)
выполнен, и он получил приращений на весь размер массива т.е.
(&a+1) == (0x100 + 1*20) /* &a+1 here it increments by array size */
== 0x120
Так что теперь ptr
указывает на
--------------------------------------
| 1 | 2 | 3 | 4 | 5 |
--------------------------------------
0x100 0x104 0x108 0x112 0x116 0x120
a |
ptr points here
Теперь, когда вы печатаете как
printf("%d %d", *(a+1), *(ptr-1));
Здесь
*(a+1) == *(0x100 + 1*4) /* multiplied by 4 bcz of elements is of int type*/
== *(0x104) /* value at 0x104 location */
== 2 (it prints 2)
И
*(ptr-1) == *(0x120 - 1*4)
== *(0x116) /* prints value at 0x116 memory location */
== 5
Примечание: - Здесь
int *ptr = (int*)(&a+1);
тип &a
имеет int(*)[5]
, то есть указатель на массив из 5 элементов, но вы преобразуете его в тип int*
, как указано @someprogrammerdude, оно нарушает строгое псевдоним и приводит к неопределенному поведению.
Правильно это
int *ptr = a+1;