Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   printf() and void * (http://www.velocityreviews.com/forums/t595554-printf-and-void.html)

Ioannis Vranos 03-02-2008 05:59 PM

printf() and void *
 
I recall from previous discussions here, that we must cast a non-void
pointer to void * before printing its value with printf("%p"). Is it
true, and if yes why?

Harald van Dijk 03-02-2008 06:19 PM

Re: printf() and void *
 
On Sun, 02 Mar 2008 19:59:19 +0200, Ioannis Vranos wrote:
> I recall from previous discussions here, that we must cast a non-void
> pointer to void * before printing its value with printf("%p"). Is it
> true, and if yes why?


Except for function pointers, which can't be printed portably at all, it
is true. There are no implicit conversions from other pointer types to
void * in the variable arguments of a function, so if any pointer type
would be accepted, how could printf know which one was passed?

Richard Heathfield 03-02-2008 06:33 PM

Re: printf() and void *
 
Harald van D?k said:

> On Sun, 02 Mar 2008 19:59:19 +0200, Ioannis Vranos wrote:
>> I recall from previous discussions here, that we must cast a non-void
>> pointer to void * before printing its value with printf("%p"). Is it
>> true, and if yes why?

>
> Except for function pointers, which can't be printed portably at all, it
> is true.


Well, no pointer value can be printed portably, since the output associated
with %p is implementation-defined. But if you mean there's no *technique*
for printing a function pointer value in ISO C, I must disagree. (If you
simply mean that there's no printf format specifier for it, then of course
you're right.)

#include <stdio.h>

int main(void)
{
int (*mp)(void) = main;
unsigned char *ucp = (unsigned char *)&mp;
size_t len = sizeof mp;
while(len--)
{
printf("%02X", *ucp++);
}
puts("");

return 0;
}

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999

Keith Thompson 03-02-2008 07:53 PM

Re: printf() and void *
 
Richard Heathfield <rjh@see.sig.invalid> writes:
> Harald van D?k said:
>> On Sun, 02 Mar 2008 19:59:19 +0200, Ioannis Vranos wrote:
>>> I recall from previous discussions here, that we must cast a non-void
>>> pointer to void * before printing its value with printf("%p"). Is it
>>> true, and if yes why?

>>
>> Except for function pointers, which can't be printed portably at all, it
>> is true.

>
> Well, no pointer value can be printed portably, since the output associated
> with %p is implementation-defined. But if you mean there's no *technique*
> for printing a function pointer value in ISO C, I must disagree. (If you
> simply mean that there's no printf format specifier for it, then of course
> you're right.)
>
> #include <stdio.h>
>
> int main(void)
> {
> int (*mp)(void) = main;
> unsigned char *ucp = (unsigned char *)&mp;
> size_t len = sizeof mp;
> while(len--)
> {
> printf("%02X", *ucp++);
> }
> puts("");
>
> return 0;
> }


On a system with CHAR_BIT > 8, the above would wor, but it could
produce ambiguous results. For example, the output "12345" could be
result of bytes 0x123 and 0x45 or 0x12 and 0x345.

I don't believe there are any hosted implementations (i.e., ones
required to support <stdio.h> with CHAR_BIT > 8), so this is unlikely
to be an issue in practice -- though the systems, mostly DSPs, that do
have CHAR_BIT > 8 may well support stdio even though they're not
required to.

Another possible issue with the above is the order in which it prints
the bytes. On one system, I ran the above code with an added line:

printf("main = %p\n", (void*)main); /* non-portable extension */

and got:

A4830408
main = 0x80483a4

There are always tradeoffs. If you want to ensure that the output is
sensible for the platform's address representation, *and* if the
implementation supports converting a function pointer to void*, *and*
if you don't mind your code being non-portable, you can use "%p" with
a cast. On systems that don't support the conversion, the code is
likely to be rejected rather than to misbehave silently.

If you want to get *really* fancy, you can write a function that tests
the byte ordering of some integer type, assume that that corresponds
to the pointer representation, and use that to determine the order in
which to display the bytes. And you can insert, say, a ':' character
between successive bytes to ensure it's unambiguous (or you can check
the value of CHAR_BIT).

--
Keith Thompson (The_Other_Keith) <kst-u@mib.org>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Harald van Dijk 03-02-2008 08:30 PM

Re: printf() and void *
 
On Sun, 02 Mar 2008 18:33:12 +0000, Richard Heathfield wrote:
> Harald van D?k said:
>> On Sun, 02 Mar 2008 19:59:19 +0200, Ioannis Vranos wrote:
>>> I recall from previous discussions here, that we must cast a non-void
>>> pointer to void * before printing its value with printf("%p"). Is it
>>> true, and if yes why?

>>
>> Except for function pointers, which can't be printed portably at all,
>> it is true.

>
> Well, no pointer value can be printed portably, since the output
> associated with %p is implementation-defined. But if you mean there's no
> *technique* for printing a function pointer value in ISO C, I must
> disagree. (If you simply mean that there's no printf format specifier
> for it, then of course you're right.)
>
> #include <stdio.h>
>
> int main(void)
> {
> int (*mp)(void) = main;
> unsigned char *ucp = (unsigned char *)&mp; size_t len = sizeof mp;
> while(len--)
> {
> printf("%02X", *ucp++);
> }
> puts("");
>
> return 0;
> }
>
> <snip>


Your example prints the representation of a function pointer, not its
value. If multiple function pointer representations exist for one value,
there is no portable way to print the value in such a way that the
different representations become indistinguishable.

Ioannis Vranos 03-02-2008 08:53 PM

Re: printf() and void *
 
Harald van Dijk wrote:
> On Sun, 02 Mar 2008 19:59:19 +0200, Ioannis Vranos wrote:
>> I recall from previous discussions here, that we must cast a non-void
>> pointer to void * before printing its value with printf("%p"). Is it
>> true, and if yes why?

>
> Except for function pointers, which can't be printed portably at all, it
> is true. There are no implicit conversions from other pointer types to
> void * in the variable arguments of a function, so if any pointer type
> would be accepted, how could printf know which one was passed?



In printf() in general, if we want to print the numeric value of a
signed char and of an unsigned char using %d and %u respectively, should
we cast the variable value to the expected type (int and unsigned
respectively)?

santosh 03-02-2008 09:05 PM

Re: printf() and void *
 
Ioannis Vranos wrote:

> Harald van Dijk wrote:
>> On Sun, 02 Mar 2008 19:59:19 +0200, Ioannis Vranos wrote:
>>> I recall from previous discussions here, that we must cast a
>>> non-void pointer to void * before printing its value with
>>> printf("%p"). Is it true, and if yes why?

>>
>> Except for function pointers, which can't be printed portably at all,
>> it is true. There are no implicit conversions from other pointer
>> types to void * in the variable arguments of a function, so if any
>> pointer type would be accepted, how could printf know which one was
>> passed?

>
>
> In printf() in general, if we want to print the numeric value of a
> signed char and of an unsigned char using %d and %u respectively,
> should we cast the variable value to the expected type (int and
> unsigned respectively)?


It shouldn't be necessary, at least as far as I can see.


Micah Cowan 03-02-2008 09:39 PM

Re: printf() and void *
 
Ioannis Vranos <ivranos@nospam.no.spamfreemail.gr> writes:

> Harald van Dijk wrote:
>> On Sun, 02 Mar 2008 19:59:19 +0200, Ioannis Vranos wrote:
>>> I recall from previous discussions here, that we must cast a non-void
>>> pointer to void * before printing its value with printf("%p"). Is it
>>> true, and if yes why?

>>
>> Except for function pointers, which can't be printed portably at
>> all, it is true. There are no implicit conversions from other
>> pointer types to void * in the variable arguments of a function, so
>> if any pointer type would be accepted, how could printf know which
>> one was passed?

>
>
> In printf() in general, if we want to print the numeric value of a
> signed char and of an unsigned char using %d and %u respectively,
> should we cast the variable value to the expected type (int and
> unsigned respectively)?


If you're going to use %u for unsigned char, yeah, a cast is a good
idea for maximally correct code. Using %d for either char, signed char
or unsigned char does not require a cast, as it will be promoted to
int in any case.

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/

Peter Nilsson 03-03-2008 03:40 AM

Re: printf() and void *
 
Keith Thompson <ks...@mib.org> wrote:
> Richard Heathfield <r...@see.sig.invalid> writes:
> > #include <stdio.h>
> >
> > int main(void)
> > {
> > * int (*mp)(void) = main;
> > * unsigned char *ucp = (unsigned char *)&mp;
> > * size_t len = sizeof mp;
> > * while(len--)
> > * {
> > * * printf("%02X", *ucp++);
> > * }
> > * puts("");

>
> > * return 0;
> > }

>
> On a system with CHAR_BIT > 8, the above would wor[k],
> but it could produce ambiguous results. *For example,
> the output "12345" could be result of bytes 0x123 and
> 0x45 or 0x12 and 0x345.


Then fix it dear Henry. :-)

#define CHAR_NIBBLES ((CHAR_BIT + 3)/4)
printf("%0*X", CHAR_NIBBLES, 0u + *ucp++);

<snip>
> Another possible issue with the above is the order in
> which it prints the bytes. *On one system, I ran the
> above code with an added line:
>
> * * printf("main = %p\n", (void*)main);
> /* non-portable extension */
>
> and got:
>
> A4830408
> main = 0x80483a4
>
> There are always tradeoffs.


Neither is intelligible IMO. But the advantage of
printing bytes is that you _know_ the format (and
width) of the output. That is quite significant in
the hand full of cases where you actually _want_
to print an address!

--
Peter

Peter Nilsson 03-03-2008 03:45 AM

Re: printf() and void *
 
Harald van Dk <true...@gmail.com> wrote:
> ... [the] example prints the representation of a function
> pointer, not its value.


It's value is determined by the representation.

> If multiple function pointer representations exist for
> one value, there is no portable way to print the value
> in such a way that the different representations become
> indistinguishable.


How is this any different to the case for %p? The only
thing you're guaranteed is that if you read via %p you'll
get a pointer that compares equal to the original.

The 'hex dump' approach has the same guarantee.

--
Peter


All times are GMT. The time now is 11:02 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.