The result of b - a
is only defined when both a
and b
point to elements of the same char array. This requirement can also be interpreted as a
and b
pointing to bytes belonging to the same object, since every object can be re-interpreted as a char array.
Otherwise, the result is undefined. I.e. an attempt to subtract such pointers results in undefined behavior.
When the result is defined, it has ptrdiff_t
type. ptrdiff_t
is a typedef name and what type is hiding behind that typedef name is implementation-defined. The type is known to be signed though.
Also note, that C language does not guarantee that ptrdiff_t
is large enough to hold the result of any subtraction, even if the pointers are pointing to the elements of the same array. If the pointers are too far apart for the type ptrdiff_t
to accomodate the result, the behavior is undefined.
There's no specific printf
format specifier for ptrdiff_t
even in C99, so you'll probably be better off converting it to a sufficiently large signed integer type and use a format specifier for that type
printf("%ld\n", (long) (b - a));
Correction: C99 does have a length modifier for ptrdiff_t
. The proper way to print the result in C99 would be
printf("%td\n", b - a);
Note that t
is a length modifier. It can be combined with d
, o
, u
, x
or X
conversion specifiers, depending on what output format you want to obtain. In C89/90 you would still have to stick with using a sufficiently large signed type.
P.S. You said that you can't imagine it failing on a 32-bit or 64-bit machine. In fact, it is very easy to imagine (or to actually make it) fail. You see the ptrdiff_t
on a 32-bit machine is usually a 32-bit type. Since it is a signed type, it has only 31 bit available to represent the magnitude of the value. If you take two pointers that are farther apart (i.e. require 32 bits to represent the "distance"), the result of b - a
will overflow and will be meaningless. In order to prevent this failure you'd need at least 33-bit signed ptrdiff_t
on a 32-bit machine, and at least 65-bit signed ptrdiff_t
on 64-bit machine. Implementations normally don't do that, they just use the "permission" from the standard to produce undefined behavior on the overflow.