Результат b - a
определяется только тогда, когда и a
, и b
указывают на элементы одного и того же массива символов. Это требование также можно интерпретировать как a
и b
, указывающие на байты, принадлежащие одному и тому же объекту, поскольку каждый объект может быть повторно интерпретирован как массив символов.
В противном случае результат не определен. То есть попытка вычесть такие указатели приводит к неопределенному поведению.
Когда результат определен, он имеет тип ptrdiff_t
. ptrdiff_t
- это имя определения типа, и тип, который скрывается за этим именем определения типа, определяется реализацией. Известно, что тип подписан.
Также обратите внимание, что язык C не гарантирует, что ptrdiff_t
будет достаточно большим, чтобы содержать результат любого вычитания, даже если указатели указывают на элементы одного и того же массива. Если указатели слишком далеко друг от друга для типа ptrdiff_t
, чтобы вместить результат, поведение не определено.
Нет конкретного спецификатора формата printf
для ptrdiff_t
даже в C99, поэтому вам, вероятно, будет лучше преобразовать его в достаточно большой целочисленный тип со знаком и использовать для этого типа спецификатор формата
printf("%ld\n", (long) (b - a));
Исправление: C99 имеет модификатор длины для ptrdiff_t
. Правильный способ напечатать результат в C99 будет
printf("%td\n", b - a);
Обратите внимание, что t
является модификатором длины. Его можно комбинировать со спецификаторами преобразования d
, o
, u
, x
или X
, в зависимости от того, какой выходной формат вы хотите получить. В C89 / 90 вам все равно придется придерживаться достаточно большого типа со знаком.
P.S. Вы сказали, что не можете себе представить, что он выйдет из строя на 32-битной или 64-битной машине. На самом деле, очень легко представить (или сделать это) неудачу. Вы видите ptrdiff_t
на 32-битном компьютере, как правило, 32-битного типа. Так как это тип со знаком, у него есть только 31 бит для представления величины значения. Если вы возьмете два указателя, которые находятся дальше друг от друга (то есть для представления «расстояния» требуется 32 бита), результат b - a
будет переполнен и будет бессмысленным. Чтобы предотвратить эту ошибку, вам понадобится как минимум 33-битная подпись ptrdiff_t
на 32-битной машине и как минимум 65-битная подпись ptrdiff_t
на 64-битной машине. Реализации, как правило, этого не делают, они просто используют «разрешение» из стандарта для создания неопределенного поведения при переполнении.