Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Flags and field width with %p format for printf()?

505 views
Skip to first unread message

Jonathan Leffler

unread,
Apr 30, 2004, 5:41:05 PM4/30/04
to
A close reading of the C Standard as published in the Wiley book
suggests that using a conversion specification such as %-10.8p is not
strictly supported. If that's correct, then any use of a precision
qualifier is invoking undefined behaviour and could create a flurry of
nasal demons. However, there are no constraints on the use of flags
or field width, so conversion specifications such as %-10p or %10p are
legitimate and fully defined (within the limitation that the output
from a %p conversion specification is implementation defined).

The standard section 7.19.16.1 includes the information:

- Zero or more flags [...]
- An optional minimum field width [...]
- An optional precision that gives the maximum number [...] for d, i,
o, u, x, and X [...] a, A, e, E, f, and F [...] g and G [...] s
conversions. [...] If a precision appears with any other conversion
specicfier, the behaviour is undefined.

It is undefined what effect the space, zero, plus and hash (sharp,
octothorpe, pound, #) flags have on %p; the # and 0 are explicitly
undefined, and space and plus are implicitly undefined - the standard
talks about their effect on signed conversions and I presume that
'void *' is neither signed nor unsigned within the meaning of this
term (a cross-reference to where that is specified would be
appreciated).

Limited empirical evidence (32-bit Solaris 8) shows that "<%-10.8p>"
does work and produces a left-justified 8-digit hexadecimal address
using lower case letters with two blanks before the close angle
bracket, and "<%10p>" produces a right-justified 8-digit address with
two blanks after the open angle bracket - assuming a sufficiently
large address value is passed in.

It isn't technically legitimate to ask here whether any
implementations are likely to generate nasal demons if faced with
"%-10.8p" - they are permitted to do so, and that's enough. But if
anyone is willing to contribute an opinion on the actual likelihood of
implausible behaviour (such as a program crash) vs a plausible output
for any specific implementations, I'd appreciate the input.

Tbanks,
Jonathan Leffler <jlef...@us.ibm.com>

David R Tribble

unread,
May 3, 2004, 12:09:14 PM5/3/04
to
Jonathan Leffler wrote:
> A close reading of the C Standard as published in the Wiley book
> suggests that using a conversion specification such as %-10.8p is not
> strictly supported. [...]

>
> Limited empirical evidence (32-bit Solaris 8) shows that "<%-10.8p>"
> does work and produces a left-justified 8-digit hexadecimal address
> using lower case letters with two blanks before the close angle
> bracket, and "<%10p>" produces a right-justified 8-digit address with
> two blanks after the open angle bracket - assuming a sufficiently
> large address value is passed in.

FWIW, I've used "%08p" on Win32 and several flavors of Unix, and I always
got an 8-digit hex address. I've used "%016p" on 64-bit DEC Alpha Unix
with similar results.

I've never used a format spec that resulted in leading spaces. Your results
make sense, though, if we assume that the implementation of the "%p" format
spec for printf() simply converts the pointer arg into an unsigned [long] int
and then uses the same formatting code as for "%x". (That's probably how I
would do it, being the prototypically lazy programmer that I am.)

In fact, I would be willing to bet that many implementations of printf("%p")
produce the same results as the equivalent printf("%x") (except for systems
with strange pointer representations). Which, from the point of view of the
standard, is probably a reasonable approach to take, since many architectures
represent addresses as number-like values.

Methinks, though, that the omission from the standard of any explicit
semantics for rendering pointer values was done on purpose, if for no other
reason than to allow for systems with "strange" pointer representations, e.g.,
16-bit DOS/Intel, which prefers pointers to be displayed like "C870:14C4".
For these kinds of systems, the justification and padding choices are probably
best left up to the implementor.

Remember that 16-bit DOS (and Windows 3.1) was the one of the most prevalent
systems when C89 was adopted.

-drt

Dan Pop

unread,
May 10, 2004, 2:03:08 PM5/10/04
to

>It isn't technically legitimate to ask here whether any
>implementations are likely to generate nasal demons if faced with
>"%-10.8p" - they are permitted to do so, and that's enough. But if
>anyone is willing to contribute an opinion on the actual likelihood of
>implausible behaviour (such as a program crash) vs a plausible output
>for any specific implementations, I'd appreciate the input.

If asked to check printf headers, gcc warns about the precision
specification and glibc apparently ignores it:

fangorn:~/tmp 38> cat test.c
#include <stdio.h>

int main()
{
printf("|%-12.6p|\n", (void *)0x12345678);
return 0;
}
fangorn:~/tmp 39> gcc -Wall test.c
test.c: In function `main':
test.c:5: warning: precision used with `%p' printf format
fangorn:~/tmp 40> ./a.out
|0x12345678 |

I can't *reallistically* imagine a run time behaviour worse than
ignoring everything and handling the conversion as if a plain %p was
actually used.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan...@ifh.de

0 new messages