Стандарт C гласит следующее относительно вычитания указателя (раздел 6.5.6p9):
Когда вычитаются два указателя, оба должны указывать на элементы одного и того же объекта массиваили один за последним элементом массива объекта; В результате получается разница индексов двух элементов массива .Размер результата определяется реализацией, а его тип (целочисленный тип со знаком) ptrdiff_t определен в заголовке.Если результат не может быть представлен в объекте этого типа, поведение не определено.Другими словами, если выражения P и Q указывают, соответственно, на i-й и j-й элементы объекта массива, выражение (P) - (Q) имеет значение i-j, если значение вписывается вобъект типа ptrdiff_t.Более того, если выражение P указывает либо на элемент объекта массива, либо на один элемент после последнего элемента объекта массива, а выражение Q указывает на последний элемент того же объекта массива, выражение ((Q) +1)- (P) имеет то же значение, что и ((Q) - (P)) + 1 и - ((P) - ((Q) +1)), и имеет нулевое значение, если выражение P указывает на одну точку послепоследний элемент объекта массива, хотя выражение (Q) +1 не указывает на элемент объекта массива. 106)
Сноска 106 гласит:
Еще один способ приблизиться к арифметике указателей - сначала преобразовать указатель (и) в символуказатель (и) : в этой схеме целочисленное выражение, добавляемое или вычитаемое из преобразованного указателя, сначала умножается на размер объекта, на который изначально указывался объект, и результирующий указатель преобразуется обратно в исходный тип. Для вычитания указателя результат разницы между символьными указателями аналогично делится на размер объекта, на который первоначально указывался. При таком рассмотрении реализация должна предоставить только один дополнительный байт (который может перекрыватьсядругой объект в программе) сразу после окончания объекта, чтобы удовлетворить требования «один за последним элементом».
Таким образом, в сноске говорится, что вычитание указателя может быть реализованы путем вычитания необработанных значений указателя и деления на размер указываемого объекта.Однако это не обязательно должно быть реализовано таким образом.
Обратите также внимание, что стандарт требует, чтобы вычитание указателя выполнялось между указателями, указывающими на элементы одного и того же объекта массива (или одного элемента после конца).Если они этого не делают, то поведение не определено.На практике, если вы работаете в системе с плоской моделью памяти, вы, вероятно, по-прежнему получите «ожидаемые» значения, но вы не можете зависеть от этого.