[OpenAFS-devel] [PATCH] flexelint: fun with printf

Garrett Wollman wollman@khavrinen.lcs.mit.edu
Mon, 1 Dec 2003 15:45:07 -0500 (EST)


<<On 01 Dec 2003 11:02:10 -0500, George Talbot <gtalbot@locuspharma.com> said:

> ptrdiff_t is guaranteed by C99 (99, right?) to be the width of a
> pointer.

No.  The only guarantee of ptrdiff_t is that it can represent any
difference of two pointers, *in circumstances where taking such a
difference is defined*.  (It is, of course, also signed, unlike most
pointers.)

C99 does define a type `uintptr_t', which can hold either an unsigned
integer or a pointer -- if and only if such a conversion can be made
without losing information.  Many (all?) ISO C implementations emit a
diagnostic when an attempt is made to convert between a pointer and an
integer of a different width (which is either undefined or
implementation-defined, I don't recall which).  The only way to print
a value of type `uintptr_t' is by casting it to `uintmax_t' and
printing it using a conversion compatible with "%ju", or by casting it
to `void *' and printing it using a conversion like "%p".  Anything
else will give a diagnostic on some platform.

As a practical matter, the most pre-C99-compatible way to implement
this is:

- Use `configure' to determine whether `uintptr_t' is declared.
- If not, declare it in a custom header.
- Print using "%#lx" format and cast the argument (long)(uintptr_t).

This may lose precision, but is extremely unlikely to do so in
circumstances where the rest of the AFS code still works.

-GAWollman