Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > casting unsigned int to void*

Reply
Thread Tools

casting unsigned int to void*

 
 
Ben Bacarisse
Guest
Posts: n/a
 
      07-30-2012
"China Blue [Tor], Meersburg" <> writes:

> In article <7edfdd82-a84a-4391-8a63->,
> Fred K <> wrote:
>
>> The Xpm pixmap library contains code that casts an unsigned int
>> to a (void *), passing that as an argument to a function
>> that expects a (void *):
>>
>> /* Function prototype: */
>> xpmHashIntern (xpmHashTable *table, char *tag, void *data));
>>
>> /* Calling it, casting 3rd argument: */
>> int a = <something>;
>> xpmHashIntern(hashtable, color->string, (void *)a );
>>
>> On a 64-bit platform where pointers are 64 bits and ints
>> are 32 bits, is this safe?

>
> intptr_t is an integer which is large enough to hold a void* pointer
> encoded in an integer. This is an ancient bug dating back to the days
> when an integer was 60 bits, would always be 60 bits, and an address
> was 18 bits, and would always be 18 bits. The 80x86s had addresses (20
> bits) larger than ints (16 bits), exposing this bad assumption.


It's never been an assumption made by C -- even pre-ANSI C.

<snip>
--
Ben.
 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      07-30-2012
Fred K <> writes:
> The Xpm pixmap library contains code that casts an unsigned int
> to a (void *), passing that as an argument to a function
> that expects a (void *):
>
> /* Function prototype: */
> xpmHashIntern (xpmHashTable *table, char *tag, void *data));
>
> /* Calling it, casting 3rd argument: */
> int a = <something>;
> xpmHashIntern(hashtable, color->string, (void *)a );
>
> On a 64-bit platform where pointers are 64 bits and ints
> are 32 bits, is this safe?


Others have addressed the safety (or lack thereof) of doing this.

The "void *data" parameter is intended for passing arbitrary information
into the function. A safer way to pass an int value is to pass the
address of an int object:

int a = <something>;
int *p = malloc(sizeof *p);
/* check for allocation error */
xpmHashIntern(hashtable, color->string, p);

I used malloc to ensure that the object continues to exist as long as
it's needed; if it's a one-off object, declaring "a" as static would
also work.

This assumes, of course, that the code that retrieves the value from the
hash table knows to treat it as a pointer to an int object.

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      07-31-2012
On 7/30/2012 4:04 PM, China Blue [Tor], Meersburg wrote:
> In article <7edfdd82-a84a-4391-8a63->,
> Fred K <> wrote:
>
>> The Xpm pixmap library contains code that casts an unsigned int
>> to a (void *), passing that as an argument to a function
>> that expects a (void *):
>>
>> /* Function prototype: */
>> xpmHashIntern (xpmHashTable *table, char *tag, void *data));
>>
>> /* Calling it, casting 3rd argument: */
>> int a = <something>;
>> xpmHashIntern(hashtable, color->string, (void *)a );
>>
>> On a 64-bit platform where pointers are 64 bits and ints
>> are 32 bits, is this safe?

>
> intptr_t is an integer which is large enough to hold a void* pointer encoded in
> an integer.


intptr_t and uintptr_t are both irrelevant to the O.P.'s
question. The fact that a void* can be converted to a [u]intptr_t
which can be in turn converted to a void* with the two pointers
comparing equal does not imply that a [u]intptr_t can be converted
to a void* and then back to a [u]intptr_t with the two integers
equal.

P1 -> I -> P2, P2 == P1
I1 -> P -> I2, I2 ?= I1 (no guarantee)

> This is an ancient bug


Makes no sense. It can't be any more ancient than C99, which
introduced the types. "Bug" can be a subjective judgement, but it's
certainly debatable whether the existence of [u]intptr_t is a "bug."
People who want to convert pointers to integers and back probably
dispute your assessment.

> dating back to the days when an integer was
> 60 bits, would always be 60 bits, and an address was 18 bits, and would always
> be 18 bits. The 80x86s had addresses (20 bits) larger than ints (16 bits),
> exposing this bad assumption.


Is this supposed to be an argument that [u]intptr_t is a "bug?"
I cannot comprehend what it's supposed to be about.

> The intptr_t was eventually introduced to provide
> an integer that would always be safe to hold addresses.


Not quite. The [u]intptr_t types are optional, meaning
that they are not "always" safe to hold addresses. Also, there
has been no introduction of addresses that are safe to hold
integers. Finally, none of this is "ancient" except to pre-teens.

--
Eric Sosman
d
 
Reply With Quote
 
Mark Bluemel
Guest
Posts: n/a
 
      07-31-2012
On 30/07/2012 23:18, China Blue [Tor], Meersburg wrote:

> It was a joke illustrating a common mistake about assuming sizeofs.


Clearly an example of alternative comedy. Comedy is usually funny, this
is the alternative.

 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      07-31-2012
On 07/30/2012 08:45 PM, Eric Sosman wrote:
> On 7/30/2012 4:04 PM, China Blue [Tor], Meersburg wrote:
>> In article <7edfdd82-a84a-4391-8a63->,
>> Fred K <> wrote:
>>
>>> The Xpm pixmap library contains code that casts an unsigned int
>>> to a (void *), passing that as an argument to a function
>>> that expects a (void *):
>>>
>>> /* Function prototype: */
>>> xpmHashIntern (xpmHashTable *table, char *tag, void *data));
>>>
>>> /* Calling it, casting 3rd argument: */
>>> int a = <something>;
>>> xpmHashIntern(hashtable, color->string, (void *)a );
>>>
>>> On a 64-bit platform where pointers are 64 bits and ints
>>> are 32 bits, is this safe?

>>
>> intptr_t is an integer which is large enough to hold a void* pointer encoded in
>> an integer.

>
> intptr_t and uintptr_t are both irrelevant to the O.P.'s
> question. ...


No, they are not.

> ... The fact that a void* can be converted to a [u]intptr_t
> which can be in turn converted to a void* with the two pointers
> comparing equal does not imply that a [u]intptr_t can be converted
> to a void* and then back to a [u]intptr_t with the two integers
> equal.
>
> P1 -> I -> P2, P2 == P1
> I1 -> P -> I2, I2 ?= I1 (no guarantee)


Agreed. However, we were not told how the integer value was chosen, nor
what xpmHashIntern() did with it. If you're familiar with xpm, it might
seem obvious. However, for those of us who are not, the possibilities
are quite open-ended. One way that code similar to the code above could
have worked is as follows:

double d = 3.14;
intptr_t a = (intptr_t)(void*)&d;

xpmHashIntern(hashtable, color->string, (void*)a);

xpmHashIntern (xpmHashTable *table, char *tag, void *data))
{
/* ... stuff ... */
double *pd = data;
/* ... more stuff, making use of *pd ... */
}

Using int rather than intptr_t could therefore work on a particular
implementation, if the result of (intptr_t)(void*)d happened to be
representable as an int on that implementation. That's not something
that code intended to be portable should rely upon, but it does provide
one possible way that such non-portable code like that might have worked
on a particular implementation.

>> This is an ancient bug

>
> Makes no sense. It can't be any more ancient than C99, which
> introduced the types. "Bug" can be a subjective judgement, but it's
> certainly debatable whether the existence of [u]intptr_t is a "bug."


I didn't see anything that suggested that the existence of [u[intptr_t
was a bug. The "bug" he's referring to is the use of 'int' rather than
'intprt_t' in the original code.

....
>> dating back to the days when an integer was
>> 60 bits, would always be 60 bits, and an address was 18 bits, and would always
>> be 18 bits. The 80x86s had addresses (20 bits) larger than ints (16 bits),
>> exposing this bad assumption.

>
> Is this supposed to be an argument that [u]intptr_t is a "bug?"


No.

> I cannot comprehend what it's supposed to be about.


It's meant to be an explanation of the problem that [u]intptr_t was
invented to solve. It fails primarily due to the fact that numbers given
were apparently chosen for humorous effect, rather than plausibility. It
would have been a lot more plausible if 60 and 18 had both been changed
to 16.
--
James Kuyper
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      07-31-2012
On 07/30/2012 01:33 PM, Fred K wrote:
> The Xpm pixmap library contains code that casts an unsigned int


Here, you say that it was an unsigned int.

> to a (void *), passing that as an argument to a function
> that expects a (void *):
>
> /* Function prototype: */
> xpmHashIntern (xpmHashTable *table, char *tag, void *data));
>
> /* Calling it, casting 3rd argument: */
> int a = <something>;


But that's a signed int. The difference is irrelevant to the main point
of your question, but the discrepancy raises questions about the
accuracy of your description of the original code.

> xpmHashIntern(hashtable, color->string, (void *)a );
>
> On a 64-bit platform where pointers are 64 bits and ints
> are 32 bits, is this safe?

--
James Kuyper
 
Reply With Quote
 
88888 Dihedral
Guest
Posts: n/a
 
      08-05-2012
James Kuyper於 2012年7月31日星期二UTC+8下午7時26分39秒 寫道:
> On 07/30/2012 01:33 PM, Fred K wrote:
>
> > The Xpm pixmap library contains code that casts an unsigned int

>
>
>
> Here, you say that it was an unsigned int.
>
>
>
> > to a (void *), passing that as an argument to a function

>
> > that expects a (void *):

>
> >

>
> > /* Function prototype: */

>
> > xpmHashIntern (xpmHashTable *table, char *tag, void *data));

>
> >

>
> > /* Calling it, casting 3rd argument: */

>
> > int a = <something>;

>
>
>
> But that's a signed int. The difference is irrelevant to the main point
>
> of your question, but the discrepancy raises questions about the
>
> accuracy of your description of the original code.
>
>
>
> > xpmHashIntern(hashtable, color->string, (void *)a );

>
> >

>
> > On a 64-bit platform where pointers are 64 bits and ints

>
> > are 32 bits, is this safe?

>
> --
>
> James Kuyper




James Kuyper於 2012年7月31日星期二UTC+8下午7時26分39秒 寫道:
> On 07/30/2012 01:33 PM, Fred K wrote:
>
> > The Xpm pixmap library contains code that casts an unsigned int

>
>
>
> Here, you say that it was an unsigned int.
>
>
>
> > to a (void *), passing that as an argument to a function

>
> > that expects a (void *):

>
> >

>
> > /* Function prototype: */

>
> > xpmHashIntern (xpmHashTable *table, char *tag, void *data));

>
> >

>
> > /* Calling it, casting 3rd argument: */

>
> > int a = <something>;

>
>
>
> But that's a signed int. The difference is irrelevant to the main point
>
> of your question, but the discrepancy raises questions about the
>
> accuracy of your description of the original code.
>
>
>
> > xpmHashIntern(hashtable, color->string, (void *)a );

>
> >

>
> > On a 64-bit platform where pointers are 64 bits and ints

>
> > are 32 bits, is this safe?

>
> --
>
> James Kuyper


As far as I know, the valid operators of pointers are ++, --, ==, =,
and various explicit type castings, ( Type *), in the C language standards..

All other operations of pointers are platform-dependent.

If the compiler can be sure that the higher 32 bits of a 64-bit pointer
is not to be changed after ++, and --, then only the lower 32 bits are needed to be loaded into a 32 bit register.

Do we need to add more operators of pointers to be in the C standards?

But I think some trival C macros in assembly can offer the same effects.

Uhn, a more sophiscated malloc might be needed, too.

 
Reply With Quote
 
Ike Naar
Guest
Posts: n/a
 
      08-05-2012
On 2012-08-05, 88888 Dihedral <> wrote:
> As far as I know, the valid operators of pointers are ++, --, ==, =,
> and various explicit type castings, ( Type *), in the C language standards.


*, ->, &, +, +=, -, -=, -, [], <, <=, >, >=, !=, sizeof, (), &&, ||, ?:
 
Reply With Quote
 
Phil Carmody
Guest
Posts: n/a
 
      08-10-2012
Ike Naar <> writes:
> On 2012-08-05, 88888 Dihedral <> wrote:
> > As far as I know, the valid operators of pointers are ++, --, ==, =,
> > and various explicit type castings, ( Type *), in the C language standards.

>
> *, ->, &, +, +=, -, -=, -, [], <, <=, >, >=, !=, sizeof, (), &&, ||, ?:


Good list, but did you really need to mention the comma operator 18 times?

Phil
--
> I'd argue that there is much evidence for the existence of a God.

Pics or it didn't happen.
-- Tom (/. uid 822)
 
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
(int) -> (unsigned) -> (int) or (unsigned) -> (int) -> (unsigned):I'll loose something? pozz C Programming 12 03-20-2011 11:32 PM
int*unsigned int = unsigned? ciccio C++ 2 06-04-2010 01:54 PM
is vec.reserve(unsigned int) better than vec(unsigned int)? er C++ 6 09-14-2007 06:20 AM
unsigned int const does not match const unsigned int Timo Freiberger C++ 3 10-30-2004 07:02 PM
dirty stuff: f(int,int) cast to f(struct{int,int}) Schnoffos C Programming 2 06-27-2003 03:13 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