%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