integer to pinter conversion

K

Keith Thompson

SM Ryan said:
Whine to X3 committee of ANSI then. X3.159-1989, section 3.3.4

An arbitrary integer may be converted to a pointer.
The result is implementation defined.

Sounds portable to me.

[ Deliberately obnoxious quoting character corrected *yet again*. ]

Note the distinction between "implementation defined" and "portable".
The code is portable in that it's legal on all implementations, but
it's not guaranteed to do what you want.

Presumably ((void*)-1) is intended to be a unique pointer value that
doesn't necessarily point to any object, basically a secondary null
pointer value. The standard doesn't guarantee that this value is
actually unique. It's possible, though unlikely, that it could happen
to be equal to some valid pointer value. It could even be equal to
NULL.

And that's assuming that the conversion from int to void* behaves
sensibly. That's usually a safe assumption, but the standard doesn't
guarantee it. The only real guarantee about pointer/integer
conversions is that converting a void* to intptr_t or uintptr_t and
back again yields the original value, *if* intptr_t exists; even
changing -1 to (intptr_t)-1 doesn't take advantage of this, since -1
wasn't obtained by converting a void* value.

It's likely to work just fine on most or all real-world
implementations -- or it could break mysteriously when it's ported to
a new platform, forcing you to waste a week or two tracking down the
cause of the misbehavior.

And it's all unnecessary. If you want a unique void* value other than
null, just declare an unused object and take its address:

static int hidden_object;
#define ERROR_INDICATOR (void*)&hidden_object

This has the added benefit of giving a meaningful name to the unique
value, rather than inducing future maintainers to repeat this very
argument.
 
I

Irrwahn Grausewitz

SM Ryan said:
# >[email protected] wrote:
# >#
# ># void *test_func(void)
# ># {
# ># return ((void *)-1);
# ># }
# >#
# ># While returning, the integer -1 is converted to void *.
# ># Is this portable ?
# >
# >The code is portable.
#
# Nope, it's not portable. Well, unless you refer to portable as in

Whine to X3 committee of ANSI then. X3.159-1989, section 3.3.4

An arbitrary integer may be converted to a pointer.
The result is implementation defined.

C99 6.3.2.3p5
An integer may be converted to any pointer type. Except as
previously specified, the result is implementation-defined,
might not be correctly aligned, might not point to an entity of
the referenced type, and might be a trap representation.

["Except as previously specified" refers to the well-defined
and portable conversion of an integer constant expression with
the value 0 to a pointer.]
Sounds portable to me.

But it means the exact opposite: if you run across "the result is
implementation defined" in the standard, that effectively means: it's
not portable; you may use it, but be aware that the result might
differ from system to system, or compiler version to compiler version.
As others already pointed out, the result might equal NULL, or a
pointer to an actual object, or even be a trap representation.
# Three very popular meanings:
# 1. You shoot yourself in the foot.
# 2. You shoot yourself in the foot, but don't notice.
# 3. You shoot yourself in someone else's foot.

Since Unix does this, you are claiming Unix is not a popular system?

You missed the invisible smiley.

Best regards
 
D

Denis Kasak

SM said:
# SM Ryan wrote:
# > (e-mail address removed) wrote:
# > # Consider a function:
# > #
# > # void *test_func(void)
# > # {
# > # return ((void *)-1);
# > # }
# > #
# > # While returning, the integer -1 is converted to void *.
# > # Is this portable ?
# >
# > The code is portable. What it means depends on the system.
#
# I beg to differ. Your two sentences contradict themselves. If a piece of

Only in your imagination. ANSI C does not provide detailed
mandatory semantics, or it would never get out of X3. Use
fopen to create a file in a hot folder and it can trigger
any possible activity for that system. All ANSI C can specify
is that if the system allows the file to be open, you get
back a FILE* that can be used in subsequent write functions.

ANSI C doesn't give semantics of real rational operator beyond
appeals to common sense notions of addition, subtraction,
multiplication, and division. Would you regard any program
that uses float or double to be nonportable?

Your logic is flawed. The things you have offered as a counter-argument
cannot directly compare to what the OP's question was. They do *exactly*
what they are guaranteed to do and the side-effects that they *might*
cause are only a worry of the underlying operating software. Converting
integers to pointers isn't guaranteed to mean anything.

-- Denis
 
S

Simon Biber

Kenneth said:
I guess it depends what is going to be done with that value. If it
will be compared to "((void *)-1)" to signal some special condition
other than success or NULL, won't that work regardless of what is the
actual "implementation defined" behavior?

No! Consider an implementation where all-bits-one is a representation of
a null pointer. (void*)-1 may compare equal to NULL.

A sufficiently perverse implementation may make all integers, when
converted to a pointer, become null pointers.
 
S

SM Ryan

# Irrwahn Grausewitz wrote on 14/09/05 :
# > IMO, if you feel the need to convert pointers to ints and vice versa,
# > your program logic is broken.
#
# I would have said "it probably denotes a design error".

I'm sure programmers who write device drivers and operating systems
shall be enlightenned by your instruction.
 
A

Alexei A. Frounze

SM Ryan said:
# I would have said "it probably denotes a design error".

I'm sure programmers who write device drivers and operating systems
shall be enlightenned by your instruction.

Quite true. :) But OSes themselves are normally designed to run on a
particular CPU/hardware and don't have to exhibit the kind of portability
the applications should. This is the distinction to keep in mind.

Alex
 
K

Kenneth Brody

Simon Biber wrote:
[... ((void *)-1) portability ...]
No! Consider an implementation where all-bits-one is a representation of
a null pointer. (void*)-1 may compare equal to NULL.

A sufficiently perverse implementation may make all integers, when
converted to a pointer, become null pointers.

"Why did you design it that way?"
"Because the Standard says I can!"


Of course, "(void *)-1" will still compare equal to "(void *)-1", won't
it? :)

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
J

Joe Wright

SM said:
# Irrwahn Grausewitz wrote on 14/09/05 :
# > IMO, if you feel the need to convert pointers to ints and vice versa,
# > your program logic is broken.
#
# I would have said "it probably denotes a design error".

I'm sure programmers who write device drivers and operating systems
shall be enlightenned by your instruction.

SM, in the normal course of events, your signature should not appear in
this reply to your post. This because a normal newsreader will read the
line above the sig and if it is "-- " ignore the rest for the reply.
Yours is "--" and missing the space. It is therefore included in the
reply. Can you change this?

I've never written a device driver in C nor have I had the chance to
write any OS code in C. I have written all kinds of other stuff in C and
I don't remember ever having to convert pointers and ints back and
forth. Why would I have to do that?
 
E

Eric Sosman

Joe Wright wrote On 09/19/05 19:39,:
I've never written a device driver in C nor have I had the chance to
write any OS code in C. I have written all kinds of other stuff in C and
I don't remember ever having to convert pointers and ints back and
forth. Why would I have to do that?

One likely reason is memory management: You may find
that you need to decompose a pointer into multiple parts
and treat them differently. For example, you might need
to determine the "memory page" a pointer refers to and
arrange for that page to be locked in physical memory
for the duration of an I/O operation. On typical systems,
you'd do this by converting the pointer to some kind of
integer and then masking or shifting to separate "page"
from "offset."

Less system-dependent circumstances also arise. For
example, consider the job of implementing malloc() and its
associates (we are supposing that you're now acting as a
C implementor rather than a C user). One requirement on
malloc() is that it must return a pointer suitably aligned
for any data type. If your malloc() obtains memory from a
system service that doesn't guarantee alignment -- Unix'
sbrk(), for example -- you will need a way to inspect the
alignment characteristics of the addresses you receive.
Again, this is usually done by converting the address to
an integer and fiddling with the bits.

However, in user-level code it is quite rare that one
needs to convert pointers to and from integers. I'm not
saying that it's rarely done, just that it's rarely needed.
 
J

Joe Wright

Eric said:
Joe Wright wrote On 09/19/05 19:39,:



One likely reason is memory management: You may find
that you need to decompose a pointer into multiple parts
and treat them differently. For example, you might need
to determine the "memory page" a pointer refers to and
arrange for that page to be locked in physical memory
for the duration of an I/O operation. On typical systems,
you'd do this by converting the pointer to some kind of
integer and then masking or shifting to separate "page"
from "offset."

Less system-dependent circumstances also arise. For
example, consider the job of implementing malloc() and its
associates (we are supposing that you're now acting as a
C implementor rather than a C user). One requirement on
malloc() is that it must return a pointer suitably aligned
for any data type. If your malloc() obtains memory from a
system service that doesn't guarantee alignment -- Unix'
sbrk(), for example -- you will need a way to inspect the
alignment characteristics of the addresses you receive.
Again, this is usually done by converting the address to
an integer and fiddling with the bits.

However, in user-level code it is quite rare that one
needs to convert pointers to and from integers. I'm not
saying that it's rarely done, just that it's rarely needed.
Thanks for the reply. I understand now.

<OT>
Out of curiosity, did you manage to have anything at all to do with
Galaxy? I can't imagine Scott thinking all this up or going along with
it but, as I can understand what's going on, it's absolutely brilliant.
Not only is it an answer to HP and IBM with their Intel stuff, Galaxy
AMD is clearly superior.

Go Sun!
</OT>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,163
Latest member
Sasha15427
Top