%p and different pointer representations
Mark H. Colburn
mark at jhereg.Jhereg.MN.ORG
Sun Feb 26 07:50:23 AEST 1989
In article <234 at mstan.Morgan.COM> dff at Morgan.COM (Daniel F. Fisher) writes:
>Consider a hosted C implementation in which different pointers
>have different representations, i.e. (char *) is different from
>(int *) is different from (int (*)()), etc. My question is
>
>To what type should a pointer argument be cast when passing it to
>fprintf() for printing using the %p conversion specifier?
>
>In view of the following two examples, I don't see that there is
>a single correct answer that will work in all architectures. And
>since %p is part of dANS C, I assume that the answer must be the
>same for every pointer in every conforming hosted implementation.
Casting the pointer to (void *) is supposed to do what you want.
The pANS says that a void pointer is large enough to handle any
pointer type (ss 3.2.2.3), much like "char *" was supposed to
handle any pointer type in old K&R. The documentation for scanf
(ss 4.9.6.2) and printf (ss 4.9.6.1), also say that the %p is
expected to be a void pointer.
>First Example: In an IBM-PC implementation with small-data,
>large-code, the data pointers (int *), (char *), etc. are all 16
>bits., but function pointers (int (*)()), etc. are all 32 bits.
>So if I wish to print a function pointer, I cannot cast it to a
>data pointer without losing information. One the other hand,
>since the type cast used for both function pointers and data
>pointers should be the same, I must cast all data pointers to
>something that is as wide as a function pointer.
Casting the pointer to "void *" is not supposed to lose information
for any conforming implementation. On the IBM-PC, using Turbo C 2.0,
printf("main %p\n", main) will print out a segment:offset address
like so:
main 252B:000C
It does this for all memory models. (I just checked). The address
which is printed corresponds to the link map which I generated as well.
I checked this for functions, pointers to functions, static and global
data in all memory models. The results were always correct.
A side note here: the %p parameter prints the result out in an
implementation defined format, so the above example is what you get
on the IBM-PC, while on a SUN you may get:
main 0x00678A
The reason, of course, is to allow the implementation to print the
address out in whatever format is most usefull for the particular
architecture or implementation.
>Second Example: In an implementation on an architecture that is
>NOT byte addressable, int pointers and function pointers will be
>word addresses and character pointers will be wider to contain
>both a word address and a byte offset. So if I wish to print a
>character pointer, I cannot cast it to an int pointer or function
>pointer without losing information. One the other hand, since the
>type cast used for all pointers must be the same, I must cast int
>pointers and function pointers to something as wide as a character
>pointer.
The void pointer is gauranteed to be wide enough by the pANS. If it
is not able to handle this example, then you should have a serious
chat with your compiler vendor.
>So in the first example, I want to cast everything to be as wide
>as a function pointer and in the second, I want to cast everything
>to be as wide as a character pointer (which is wider than a function
>pointer). What's a programmer to do? Now if someone wants to tell
>me that I should cast to (void *) because it is guaranteed to be at
>least as wide as any pointer type in the implementation, then I will
>say, "Thank you very much", "Wonderful", "Hooray for void star" and
>"Gee, I didn't know that".
Fair enough, now you do. :-)
--
Mark H. Colburn "Look into a child's eye;
Minnetech Consulting, Inc. there's no hate and there's no lie;
mark at jhereg.mn.org there's no black and there's no white."
More information about the Comp.lang.c
mailing list