By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,686 Members | 1,510 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,686 IT Pros & Developers. It's quick & easy.

print an address

P: n/a
Hi,

I hear many say that it is better to convert address, i mean, type
cast into (void*) and print using %p identifier rather than %u, could
you let me know the specific reason behind it?

Dec 14 '06 #1
Share this Question
Share on Google+
8 Replies


P: n/a
sa*****@yahoo.co.in wrote:
Hi,

I hear many say that it is better to convert address, i mean, type
cast into (void*) and print using %p identifier rather than %u, could
you let me know the specific reason behind it?
It's the same reason that you shouldn't use %d to print variables of
type double: that's simply not what it's for.

Dec 14 '06 #2

P: n/a
sa*****@yahoo.co.in said:
Hi,

I hear many say that it is better to convert address, i mean, type
cast into (void*) and print using %p identifier rather than %u, could
you let me know the specific reason behind it?
(a) The Standard says so. This is the most compelling reason. If we proceed
according to spec, we eliminate a possible point of failure.

(b) Pointers need not have the same representation or size as unsigned ints
- and indeed on some implementations they do not.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 14 '06 #3

P: n/a
sa*****@yahoo.co.in wrote:
I hear many say that it is better to convert address, i mean, type
cast into (void*) and print using %p identifier rather than %u, could
you let me know the specific reason behind it?
Because that's what the C language standard requires. Backgroud is
that there are systems where e.g. the size of an int isn't identical
to that of a pointer and even some where a pointer can't even be
expressed as a simple number.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
Dec 14 '06 #4

P: n/a


On Thu, 14 Dec 2006, Jens Thoms Toerring wrote:
sa*****@yahoo.co.in wrote:
> I hear many say that it is better to convert address, i mean, type
cast into (void*) and print using %p identifier rather than %u, could
you let me know the specific reason behind it?

Because that's what the C language standard requires. Backgroud is
that there are systems where e.g. the size of an int isn't identical
to that of a pointer and even some where a pointer can't even be
expressed as a simple number.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de

While the previous posters have correctly pointed out the reasons,
referring to the standard, I think that an example will clarify things a
little more. Take a look at the following program (I have used %x instead
of %u, so that the outputs should be in hex, but the point is the same
if %u is used):

--------------------------------- C:\junk.c ----------------------
#include <stdio.h>
int main()
{

int i = 7;
void *p = &i;
printf("p with %%x: %x\n", (unsigned)p);
printf("p with %%lx: %lx\n",(unsigned long)p);
printf("p with %%p: %p\n",p);

return 0;
}

Now, if you compile this program under MS-DOS using Turbo C 2.01 (BTW you
can download it from Borland's Museum site), you will get different
outputs, depending on whether you are using the small memory model or
large memory model.

Small memory model:

C:\>tcc -ms JUNK.c
Turbo C Version 2.01 Copyright (c) 1987, 1988 Borland International
junk.c:
Turbo Link Version 2.0 Copyright (c) 1987, 1988 Borland International

Available memory 427920

C:\>JUNK
p with %x: ffe0
p with %lx: 74effe0
p with %p: FFE0

C:\>
Large memory model:

C:\>tcc -ml JUNK.c
Turbo C Version 2.01 Copyright (c) 1987, 1988 Borland International
junk.c:
Turbo Link Version 2.0 Copyright (c) 1987, 1988 Borland International

Available memory 427890

C:\>JUNK
p with %x: fe2
p with %lx: 7e10fe2
p with %p: 07E1:0FE2

C:\>
Notice that neither %x nor %lx provide the correct output in both cases
(the semantics of pointers changes if the small or large memory model is
used). However %p always prints out the correct value (an offset into the
current segment for the small memory model and a segment:offset pair for
the large memory model), no matter what memory model is being used.
Emil

Dec 14 '06 #5

P: n/a
>sa*****@yahoo.co.in wrote:
>> I hear many say that it is better to convert address, i mean, type
cast into (void*) and print using %p identifier rather than %u, could
you let me know the specific reason behind it?
In article <Pi*******************************@csd.cs.technion .ac.il>
Kohn Emil Dan <em***@cs.technion.ac.ilwrote:
>While the previous posters have correctly pointed out the reasons,
referring to the standard, I think that an example will clarify things a
little more. ...
[snipped: examples of incorrect output with integer formatting directives]

Similar failures will occur on machines with 32-bit "int" and
64-bit pointers. Using "%u" will print a 32-bit value, but if
pointers use more than 32 bits, which 32 bits of the pointer
(if any) will this be?

As was noted in another thread, the real point of a type system
(things like C's "char", "short", "int", "float", "double",
various pointer types, structures, and so on) is to capture
the "essential nature" of values of that type, and then work
with it. The nature of integers means that there are no fractional
parts, while the nature of floating-point numbers means that
there are fractional parts.

The essential nature of a pointer (in C anyway) is that it may
point to an object or a function, or -- in the special case of
"void *" -- the individual bytes of any particular object. Integers
do not inherently point to objects, and pointers are not necessarily
integers. (If the C99 type "intptr_t" exists, there is some integer
type that, in some sense, "works" for pointers, in some machine-dependent
fashion. But the type need not even exist, e.g., if for some reason
the hardware has only 32 and 64 bit integers, but 256-bit pointers.)

When one violates the type system (in any way, small or large),
one risks "missing out" on some part of the "essential nature" of
the violated type. To put it another way, programming is really
about abstraction: exposing only those details that need to be
exposed, while hiding all those details that can be hidden, so that
enormous and unmanageable problems shrink down into small, manageable
ones. Types are a method (not "the" method, just "a" method) of
maintaining abstractions. Violating the types violates the
abstractions, and can turn what were manageable problems into
unmanageable ones. It is not *guaranteed* to happen -- maybe the
exposed details are not, after all, overwhelming or even obnoxious
-- but it *might* happen. Prudence suggests avoiding this, at least
in "real work".

(In other words, it is OK to smash the device into smithereens only
if you are sure you are not going to need it later. Otherwise,
feel free to carefully disassemble it to examine its inner workings,
but be sure you can reassemble it later. If you do not have time
for all that, just keep it in one piece. :-) )
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Dec 14 '06 #6

P: n/a

sa*****@yahoo.co.in wrote:
Hi,

I hear many say that it is better to convert address, i mean, type
cast into (void*) and print using %p identifier rather than %u, could
you let me know the specific reason behind it?
There's no guarantee that a pointer value can be accurately represented
with an unsigned integer type. Pointer types may be physically larger
than integer types, or may have a different representation from integer
types. You may lose or garble information in the conversion.

Then there's the little problem that passing an argument of a pointer
type for a %u conversion specifier is a type mismatch, which IIRC
invokes undefined behavior.

Dec 14 '06 #7

P: n/a
sa*****@yahoo.co.in writes:
I hear many say that it is better to convert address, i mean, type
cast into (void*) and print using %p identifier rather than %u, could
you let me know the specific reason behind it?
The answers you've gotten so far have explained that pointers and
unsigned integers are not the same thing; they might have different
sizes, and they might even be passed differently as function
arguments. So, for example, if you do this:

int i;
int *ptr = &i;
printf("ptr = %u\n", ptr);

even if unsigned int (the type expected for "%u" and int* happen to
have the same size, printf is going to try to grab an unsigned int
value from the location where it expects an unsigned int argument to
have been passed to it. That might be the same place that the int*
argument was passed (say, at a certain location on the stack, or in a
particular register), but it's *possible* that integer and pointer
arguments may be passed by different mechanisms (say, in different
registers, or on different stacks). If that happens, printf will grab
an unsigned int value from a location that hasn't been set to
anything; whatever is printed will have no relationship to the value
of ptr, which is what you wanted to print.

These are just some of the infinitely many possible consequences of
undefined behavior.

But so far, I don't think anyone has explained why the cast is
necessary.

Suppose you try this:

int i;
int *ptr = &i;
printf("ptr = %p\n", ptr);

That's a little better, but you're still lying to printf; you're
passing it a value of type int*, but telling it to expect a value of
type void*. On many implementations, different pointer types have
exactly the same representation, and the code will probably "work" as
expected. But an implementation is allowed to use different
representations, not just for integers vs. pointers, but for different
pointer types.

With most functions, the compiler knows from the function's
declaration exactly what argument types it's expecting. If the actual
type doesn't match exactly, it's often possible for the compiler to
perform an implicit conversion to make it match.

For example, the free() function expects a void*, argument, but you
can pass it something of a different type (but not *too* different).
You can legally do this:

int *ptr = malloc(sizeof *ptr);
...
free(ptr);

and the int* value of ptr will be implicitly converted to void* before
it's passed to free().

But printf is a *variadic* function, meaning that it can accept an
arbitrary number and type of arguments. This is very convenient, but
it can also be dangerous. You tell printf() what types of arguments
to expect via the format string; this happens at run time, not at
compile time. Since the compiler doesn't understand the format
string, you have to make sure that all the arguments are already
*exactly* the right type. If you want to print a pointer, the way to
do this is with a cast:

printf("ptr = %p\n", (void*)ptr);

This is one of the few cases where a cast is appropriate and
necessary.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Dec 14 '06 #8

P: n/a
sa*****@yahoo.co.in wrote:
>
I hear many say that it is better to convert address, i mean, type
cast into (void*) and print using %p identifier rather than %u,
could you let me know the specific reason behind it?
Because that is guaranteed to work. Using %u isn't.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Dec 15 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion.