Сдвиг вправо на 2 - это быстрый способ деления на 4. 4 - это ваш int
размер.
Расстояние двух указателей до int
- это расстояние двух указателей char
, соответствующих указателям int
, деленным на размер int
(помните, что при добавлении целого числа к указателю целое число масштабируется на размер указателя-цели, поэтому при выполнении различий необходимо отменить это масштабирование).
Технически, вы не должны вычитать два не связанных между собой указателя (или печатать разницу с "%ld"
вместо правильного "%zd"
), так как это неопределенное поведение - стандарт позволяет вам различать только указатели, указывающие на один и тот же объект или только что прошел Тем не менее, общая int*
-дифференцирующая функция, которая сама по себе не имеет такого неопределенного поведения:
#include <stddef.h>
ptrdiff_t diff_int_ptr(int *A, int *B)
{
return A-B;
}
все равно будет переводиться в эквивалент
ptrdiff_t diff_int_ptr(int *A, int *B)
{
return ((char*)A - (char*)B) >> lg2(sizeof(int));
//strength reduced from: return ((char*)A - (char*)B) / sizeof(int)
//which is possible iff sizeof(int) is a power of 2
}
на оптимизирующем компиляторе ( годовая ссылка для x86-64 gcc и clang ), поскольку сдвиг обычно в 10 раз быстрее, чем деление на современной машине.