Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > printf() and void *

Reply
Thread Tools

printf() and void *

 
 
Harald van Dijk
Guest
Posts: n/a
 
      03-03-2008
On Sun, 02 Mar 2008 19:45:29 -0800, Peter Nilsson wrote:
> Harald van Dijk <true...@gmail.com> wrote:
>> ... [the] example prints the representation of a function pointer, not
>> its value.

>
> It's value is determined by the representation.


Of course, but that's true for all types. Should we start printing 1.01 as
a series of bytes too, then?

>> 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.


If you print the same value to printf twice, you can be sure you get the
same string twice. If you print the representation of two identical values
twice, you can't be sure you get the same string twice.
 
Reply With Quote
 
 
 
 
ymuntyan@gmail.com
Guest
Posts: n/a
 
      03-03-2008
On Mar 3, 12:19 am, Harald van D©¦k <true...@gmail.com> wrote:
> On Sun, 02 Mar 2008 19:45:29 -0800, Peter Nilsson wrote:
> > Harald van D©¦k <true...@gmail.com> wrote:
> >> ... [the] example prints the representation of a function pointer, not
> >> its value.

>
> > It's value is determined by the representation.

>
> Of course, but that's true for all types. Should we start printing 1.01 as
> a series of bytes too, then?


Isn't it what "binary file formats" is about?

> >> 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.

>
> If you print the same value to printf twice, you can be sure you get the
> same string twice. If you print the representation of two identical values
> twice, you can't be sure you get the same string twice.


You can not be sure that you'll get two identical
strings from printf("%p\n%p\n", p, p). printf() is
"better" only in that scanf() will be able to read
the string back; the "quality" of output may be
"worse" or "better" in either case.

Anyway, it was about function pointers, for which
printf() doesn't work, so...

Yevgen
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      03-03-2008
Peter Nilsson <> writes:
> 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++);


Sure. But using printing hex digits per byte likely *is* the best
format when CHAR_BIT==8.

> <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!


Sure, but using "%p" means that the implementer chooses a format
that's intended to make sense in terms of the addressing structure of
the machine. If I print the addresses of two functions using the
non-portable trick of casting to void* and using "%p", and I and get
"0x80483a4" and "0x80483b8", then that might tell me something about
the relationship between the functions, and it's very likely to match
the information in a link map. If I see "A4830480" and "B8830480",
it's a bit harder to see that relationship, or even to tell whether
the addresses make sense.

--
Keith Thompson (The_Other_Keith) <kst->
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
David Tiktin
Guest
Posts: n/a
 
      03-03-2008
On 02 Mar 2008, 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.


I'm a little unclear on the point you're making here. I would have
said that the code:

#include <stdio.h>
#include <limits.h>

int main(void)
{
printf("%d\n", INT_MAX);

return 0;
}

is a completely portable way to print the value of INT_MAX even
though what's printed is obviously implementation defined. I guess I
generally think of "portable" as meaning "will do 'the right thing'
on all platforms" so using %p is the portable way to print non-
function pointers which have been cast to void *. What happens when
you write to a text file is another example. Can't you write to a
text file portably in C even though the result is implementation
defined?

Dave

--
D.a.v.i.d T.i.k.t.i.n
t.i.k.t.i.n [at] a.d.v.a.n.c.e.d.r.e.l.a.y [dot] c.o.m
 
Reply With Quote
 
Harald van Dijk
Guest
Posts: n/a
 
      03-03-2008
On Sun, 02 Mar 2008 23:48:33 -0800, ymuntyan wrote:
> On Mar 3, 12:19 am, Harald van Dijk <true...@gmail.com> wrote:
>> On Sun, 02 Mar 2008 19:45:29 -0800, Peter Nilsson wrote:
>> > Harald van Dijk <true...@gmail.com> wrote:
>> >> ... [the] example prints the representation of a function pointer,
>> >> not its value.

>>
>> > It's value is determined by the representation.

>>
>> Of course, but that's true for all types. Should we start printing 1.01
>> as a series of bytes too, then?

>
> Isn't it what "binary file formats" is about?


I meant printing the series of bytes as hexadecimal numbers, which is not
what binary file formats are about.

>> >> 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.

>>
>> If you print the same value to printf twice, you can be sure you get
>> the same string twice. If you print the representation of two identical
>> values twice, you can't be sure you get the same string twice.

>
> You can not be sure that you'll get two identical strings from
> printf("%p\n%p\n", p, p).


The standard states that "the value of the pointer is converted to a
sequence of printing characters, in an implementation-defined manner."
This, by my reading, does not allow anything other than the value of the
pointer to have an effect on the output. In particular, it does not allow
the representation of the pointer (when multiple representations of the
same value exist) to have an effect.
 
Reply With Quote
 
Richard Heathfield
Guest
Posts: n/a
 
      03-03-2008
David Tiktin said:

> On 02 Mar 2008, Richard Heathfield <> wrote:
>

<snip>
>>
>> Well, no pointer value can be printed portably, since the output
>> associated with %p is implementation-defined.

>
> I'm a little unclear on the point you're making here. I would have
> said that the code:
>
> #include <stdio.h>
> #include <limits.h>
>
> int main(void)
> {
> printf("%d\n", INT_MAX);
>
> return 0;
> }
>
> is a completely portable way to print the value of INT_MAX even
> though what's printed is obviously implementation defined.


Right - the technique is portable, but the value isn't.

<snip>

> Can't you write to a
> text file portably in C even though the result is implementation
> defined?


Again, the technique is portable, but the value isn't. Consider:

#include <stdio.h>

int main(void)
{
FILE *fp = fopen("foo.txt", "w");
if(fp != NULL)
{
if(fputs("A\n", fp) != EOF && fclose(fp))
{
puts("All is well.");
}
}
return 0; /* if fputs failed, the stream will be closed on exit! */
}

If "All is well" is displayed (under any conforming hosted implementation),
we have created a text file, which in C terms contains one line comprising
'A' and a newline character. So the technique is portable.

But what have we actually created, in what we might call absolute terms? On
a PC under Windows, the file will contain three bytes, with values 65, 13,
and 10 (obviously I'm using decimal representation here). On an old-style
Mac, it would contain just two bytes: 65, 13. On a Linux box (or, I
*think*, a modern Mac), it would contain 65, 10. On an IBM mainframe,
well, don't ask(!), but to start off with, that 'A' would be 193 rather
than 65. The point is that, whilst the output can be interpreted
consistently within the machine/OS/implementation combination, moving that
file to another (disparate) system will (or at least may) result in that
interpretation becoming invalidated unless some kind of data massage is
performed.

So I guess it all depends on what we mean by "portable"!

--
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
 
Reply With Quote
 
Barry Schwarz
Guest
Posts: n/a
 
      03-04-2008
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?


Different types of object pointers are allowed to have different sizes
and different representations. But you are allowed to convert
(explicitly or implicitly) between any of these types and void* with
no loss of information.

scanf must accept many different kinds of pointers. %s requires a
char*, %d requires an int*, etc. Therefore, it is not possible to
have a rule that says any pointer in the variadic portion of the
argument list would be "promoted" to void*. (There is such a rule
that says short and char are promoted to int and float is promoted to
double in the variadic portion of an argument list.) [scanf could
have been designed to accept void pointers across the board but then
compilers could not optionally check the arguments against the
conversion specifications.]

Rather than provide printf with a slew of conversion specifications
(which could have also allowed function pointers to be printed), %p is
used for all object pointers after they have been converted to void*.
Since there is no automatic conversion to void* (for the variadic
portion of an argument list), you must direct the compiler to perform
the conversion by casting the value.


Remove del for email
 
Reply With Quote
 
Peter Nilsson
Guest
Posts: n/a
 
      03-04-2008
Barry Schwarz <schwa...@doezl.net> wrote:
> ...
> scanf must accept many different kinds of pointers.
>*%s requires a char*, %d requires an [int], etc.


True.

>*Therefore, it is not possible to have a rule that says
> any pointer in the variadic portion of the argument
> list would be "promoted" to void*.


Why not?

[Not that I'd want to see such a rule.]

--
Peter
 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      03-04-2008
Peter Nilsson wrote:
> Barry Schwarz <schwa...@doezl.net> wrote:
>> ...
>> scanf must accept many different kinds of pointers.
>> %s requires a char*, %d requires an [int], etc.

>
> True.
>
>> Therefore, it is not possible to have a rule that says
>> any pointer in the variadic portion of the argument
>> list would be "promoted" to void*.

>
> Why not?


They SHOULD be promoted to void. The type required is spelled out
by the format string, so they can always be converted back to the
appropriate form. This is one reason why the format string has to
agree with the types received. All scanf needs to know is in the
format, and in the void* pointer.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.



--
Posted via a free Usenet account from http://www.teranews.com

 
Reply With Quote
 
Barry Schwarz
Guest
Posts: n/a
 
      03-04-2008
On Mon, 3 Mar 2008 18:13:09 -0800 (PST), Peter Nilsson
<> wrote:

>Barry Schwarz <schwa...@doezl.net> wrote:
>> ...
>> scanf must accept many different kinds of pointers.
>>*%s requires a char*, %d requires an [int], etc.


Interesting that your reader didn't quote what I wrote.

>
>True.
>
>>*Therefore, it is not possible to have a rule that says
>> any pointer in the variadic portion of the argument
>> list would be "promoted" to void*.

>
>Why not?


Because then scanf would not be receiving the expected type. Changing
scanf so this could be done was mentioned two sentences later.

>
>[Not that I'd want to see such a rule.]



Remove del for email
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
What is the difference between void proba(); and void proba(void); ??? PencoOdStip@gmail.com C++ 1 05-23-2007 07:12 PM
what is the difference, void func(void) and void fucn() noblesantosh@yahoo.com C Programming 5 07-22-2005 04:38 PM
"void Method()" vs "void Method(void)" Ollej Reemt C++ 7 04-22-2005 03:47 AM
returning a void (*)(void) Sergio C++ 6 01-05-2005 08:30 PM
`void **' revisited: void *pop(void **root) Stig Brautaset C Programming 15 10-28-2003 09:03 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57