Указатель арифметики и литья - PullRequest
0 голосов
/ 05 декабря 2018
short x = 5;        
short*ptr = &x;     
short *ptr2 = ptr+5; 

cout << ptr2 - ptr << endl;
cout << (long) ptr2 - (long)ptr << endl;

Я понимаю, что указатели хранят адреса, но я не понимаю, почему ответ для обеих строк не равен 10.

Разве это не ptr2 = адрес указателя + sizeof (short) *5

Ответы [ 3 ]

0 голосов
/ 05 декабря 2018

Арифметика указателя выражается через элементы типа, на который указывает указатель.

ptr+5 увеличивается ptr на 5 * sizeof(short) байт.

Результат ptr2 - ptr равно 5, потому что компилятор знает, что ptr и ptr2 указывают на short элементы, и поэтому он делит разницу двух адресов памяти на sizeof(short).Число short элементов между этими двумя адресами памяти равно 5.

В то время как (long) ptr2 - (long)ptr не арифметика указателей, это просто обычная целочисленная арифметика.Он вычисляет разницу двух адресов памяти как есть, независимо от того, на что они указывают.Поскольку между двумя адресами памяти имеется 5 short элементов, а в вашем случае sizeof(short) явно составляет 2 байта, расстояние между двумя адресами памяти составляет 10 байтов.

0 голосов
/ 05 декабря 2018

Арифметика указателей ведет себя алгебраически.

, если y = x + 5, тогда y - x = 5. Это верно, если x и y являются целыми числами, или x и y являются указателями на один и тот же тип.

Обратите внимание, что вы не можете делать z = y + x с указателями.z НЕ равен 2x + 5. Он даже не компилируется.Вы не можете добавить два указателя, но вы можете взять разницу между двумя указателями (и получить количество элементов).

0 голосов
/ 05 декабря 2018

Адреса памяти могут быть на расстоянии десяти байтов, но это не то, как работает сложение / вычитание указателя.Используемые значения масштабируются в зависимости от размера типа данных, поэтому для двухбайтовых short значения будут вдвое меньше, чем вы ожидаете от фактических адресов памяти (если ваш тип данных былодин байт char, он будет работать так, как вы, вероятно, ожидаете).

Это действительно ничем не отличается от добавления pointer + 4, которое дает вам адрес пятого элемента в массиве, не адрес пять байтов перед указателем.

Это рассматривается в разделе [expr.add] стандарта (текст из C++17):

Когда два указателя наэлементы одного и того же объекта массива вычитаются, тип результата - определенный целочисленной реализацией тип со знаком;этот тип должен быть того же типа, который определен как std::ptrdiff_t в заголовке <cstddef> (21.2).

Если выражения P и Q указывают соответственно на элементы x[i] и x[j] одного и того же объекта массива x, выражение P - Q имеетзначение i − j; в противном случае поведение не определено.


Конечно, в любом случае это спорный вопрос в вашем случае, поскольку, согласно этой цитате,что вы делаете, это неопределенное поведение.Вычитание указателя не определено, если оба указателя не находятся в одном и том же массиве (или на один байт после указанного массива).

...