Это согласуется с тем, как ведет себя указатель указателя. Это означает, что p1 + (p2 - p1) == p2
*.
Добавление указателя (добавление целого к указателю) ведет себя аналогичным образом: p1 + 1
дает вам адрес следующего элемента в массиве, а не следующий байт в массиве - это было бы довольно бесполезно и небезопасно.
C мог быть спроектирован так, чтобы указатели добавлялись и вычитались так же, как целые числа, но это означало бы:
p2 = p1 + n * sizeof(*p1)
вместо p2 = p1 + n
n = (p2 - p1) / sizeof(*p1)
вместо n = p2 - p1
Это приведет к тому, что код
*: предполагается, что разница между p1 и p2 является точным кратным типа, на который они указывают. Если они находятся в одном массиве памяти, это будет верно. Если это не так, то это не имеет большого значения, делая арифметику указателей на них.