Существует нет гарантии того, что ваши указатели имеют тот же размер, что и ваши целые числа, поэтому вам не следует использовать %d
в качестве спецификатора формата.
Я видел проблемыаналогично этому, когда люди передают long
переменные в printf
со спецификатором для int
.Так как long был шире int
, это сбило с толку printf
относительно того, где что-то было в стеке.
Вы должны использовать %p
для указателей.Есть также множество других проблем с этим кодом, в соответствии со стандартами.Попробуйте в качестве отправной точки следующее:
#include <stdio.h>
int main (void) {
int *x, *y;
int a = 23, b = 56;
x=&a; y=&b;
printf ("%p %p\n", x, y);
x++; y++;
printf ("%p %p\n", x, y);
return 0;
}
Вот одно возможное объяснение (благодаря комментарию от Майкла Берра):
Допустим, ваш указатель32-битные, а ваши целые 16-битные и что вы используете архитектуру с прямым порядком байтов (например, Intel).
Далее, предположим, что адрес a
равен 0x12345678
, а адрес b
is 0x1234567a
.
Когда вы передаете их в printf
, вы помещаете два 32-битных значения в стек, но printf
считывает только два 16-битных значения, так как было сказано, что с %d %d
спецификаторы формата:
himem
--------
/ | 0x12 |
push | 0x34 |
| | 0x56 |
\ | 0x78 |
--------
/ | 0x12 | \ printf reads 0x1234
push | 0x34 | /
| | 0x56 | \ printf reads 0x567a
\ | 0x7a | /
--------
lomem
Затем, когда вы увеличиваете оба указателя и снова вызываете printf
, вы получаете:
himem
--------
/ | 0x12 |
push | 0x34 |
| | 0x56 |
\ | 0x7a |
--------
/ | 0x12 | \ printf reads 0x1234
push | 0x34 | /
| | 0x56 | \ printf reads 0x567c
\ | 0x7c | /
--------
lomem
В этом сценарии вы можете увидеть, почему он может выглядетькак если бы был увеличен только один указатель, но реальная проблема заключается в том, что вы не печатаете указатели, скорее вы печатаете наиболее значительную половину одного из них (что, вероятно, не изменится) инаименее значимая половина того же (которыйплохо меняется).