Go Back   Rhinocerus > Newsgroup > Newsgroup comp.lang.c

Reply
 
Thread Tools Display Modes
  #1 (permalink)  
Old 07-30-2012, 05:33 PM
Fred K
Guest
 
Posts: n/a
Default casting unsigned int to void*

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?
Reply With Quote
Alt Today
Advertising
 
and become member of Rhinocerus
Standard Sponsored Links

  #2 (permalink)  
Old 07-30-2012, 05:59 PM
Eric Sosman
Guest
 
Posts: n/a
Default Re: casting unsigned int to void*

On 7/30/2012 1:33 PM, 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?


For suitable definitions of "safe," yes. Presumably the goal
is to be able to convert the `void*' back to an `unsigned(?) int'
and recover the original "<something>". If so,

- The C language does not guarantee that this will work (no,
not even if you use `intptr_t' or `uintptr_t'), but

- It will work on every 64-bit machine I've ever encountered,
and I haven't heard of any where it wouldn't.

--
Eric Sosman
esosman@ieee-dot-org.invalid
Reply With Quote
  #3 (permalink)  
Old 07-30-2012, 06:14 PM
James Kuyper
Guest
 
Posts: n/a
Default Re: casting unsigned int to void*

On 07/30/2012 01:33 PM, 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?



The fact that pointers are 64 bits and ints are 32 bits makes it more
difficult for this to work, but not impossible. On a platform where both
are the same size, it's more likely to work, but that's still not
guaranteed. The precise requirements are as follows:

Converting an integer constant expression with a value of 0 to void* is
guaranteed by the standard to result in a null pointer value.

Converting a pointer to void into either intptr_t or uintptr_t produces
a value that can be converted back to void*, resulting in a pointer that
is equivalent to the original pointer. Those two types are optional; if
supported, they are defined in <stdint.h>, which was introduced in C99.
You can check whether they are supported by checking whether INTPTR_MAX
or UINTPTR_MAX are #defined.

In all other cases, while converting an integer value to a pointer is
permitted, "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."

Whether or not this code works correctly is therefore
implementation-specific. It would never have been written and released
unless it actually did work, somewhere, but that's no guarantee that it
will work anywhere else.
Reply With Quote
  #4 (permalink)  
Old 07-30-2012, 06:23 PM
Fred K
Guest
 
Posts: n/a
Default Re: casting unsigned int to void*

On Monday, July 30, 2012 11:14:34 AM UTC-7, James Kuyper wrote:
> On 07/30/2012 01:33 PM, Fred K wrote: > The Xpm pixmap library contains code that casts an unsigned int > to a (void *), passing that as an argumentto 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? The fact that pointers are64 bits and ints are 32 bits makes it more difficult for this to work, butnot impossible. On a platform where both are the same size, it's more likely to work, but that's still not guaranteed. The precise requirements are as follows: Converting an integer constant expression with a value of 0 to void* is guaranteed by the standard to result in a null pointer value. Converting a pointer to void into either intptr_t or uintptr_t produces a value that can be converted back to void*, resulting in a pointer that is equivalent to the original pointer. Those two types are optional; if supported, they are defined in <stdint.h>, which was introduced in C99. You can check whether they are supported by checking whether INTPTR_MAX or UINTPTR_MAX are #defined. In all other cases, while converting an integer value to a pointer is permitted, "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." Whether or not this code works correctly is therefore implementation-specific. It would never have been written and released unless it actually did work, somewhere, but that's no guarantee that it will work anywhere else.


Well, it was written a long time ago, and for platforms where the size of an int was the same size as a pointer. So far, I haven't found a problem with it on an HP-UX, SGI, Sun, AIX; I'm now porting it to several flavors of (64-bit) Linux, and iPad. Time will tell...
Reply With Quote
  #5 (permalink)  
Old 07-30-2012, 06:46 PM
Alan Curry
Guest
 
Posts: n/a
Default Re: casting unsigned int to void*

There was some really unforgivable formatting in here, especially the more
deeply quoted parts, so I chopped them out. Google Groups sucks! Get a
real newsreader!

In article <afc78550-acc3-4f3f-b9e6-5dcbe1e33061@googlegroups.com>,
Fred K <fred.l.kleinschmidt@gmail.com> wrote:
[about xpm]
>
>Well, it was written a long time ago, and for platforms where the size
>of an int was the same size as a pointer. So far, I haven't found a
>problem with it on an HP-UX, SGI, Sun, AIX; I'm now porting it to
>several flavors of (64-bit) Linux, and iPad. Time will tell...


Xpm isn't some dead artifact you just dug up that nobody else remembers. It has
been continuously maintained and is still distributed by x.org.

Why can't you use their version? It should already be bundled with your
Linux distribution.

--
Alan Curry
Reply With Quote
  #6 (permalink)  
Old 07-30-2012, 06:47 PM
bartek szurgot
Guest
 
Posts: n/a
Default Re: casting unsigned int to void*

On 07/30/2012 07:33 PM, 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?


it is not safe - standard does not give you any guarantees on that. it
may work, on some machines. if the intend was to pass an int value via
void* it should be int's address, not the value (i.e. void foo(void*);
foo(&a)). you should probably contact the maintainer of this code.

--
pozdrawiam serdecznie / best regards,
bartek szurgot
/* http://www.baszerr.eu */
Reply With Quote
  #7 (permalink)  
Old 07-30-2012, 07:03 PM
Edward A. Falk
Guest
 
Posts: n/a
Default Re: casting unsigned int to void*

In article <jv6i1p$ch0$1@dont-email.me>,
Eric Sosman <esosman@ieee-dot-org.invalid> wrote:
>On 7/30/2012 1:33 PM, Fred K wrote:
>
> For suitable definitions of "safe," yes. Presumably the goal
>is to be able to convert the `void*' back to an `unsigned(?) int'
>and recover the original "<something>". If so,
>
> - The C language does not guarantee that this will work (no,
> not even if you use `intptr_t' or `uintptr_t'), but
>
> - It will work on every 64-bit machine I've ever encountered,
> and I haven't heard of any where it wouldn't.


Agreed. The spec may not support it, but it should be safe on
most machines, as long as the size of void* is >= the size of int.

It would fail on a 286 with the wrong compiler options, and maybe a
PDP-11, but would be safe on any other machine I've ever worked on.

--
-Ed Falk, falk@despams.r.us.com
http://thespamdiaries.blogspot.com/
Reply With Quote
  #8 (permalink)  
Old 07-30-2012, 07:09 PM
Fred K
Guest
 
Posts: n/a
Default Re: casting unsigned int to void*

On Monday, July 30, 2012 11:46:51 AM UTC-7, Alan Curry wrote:
> There was some really unforgivable formatting in here, especially the more deeply quoted parts, so I chopped them out. Google Groups sucks! Get a real newsreader! In article <afc78550-acc3-4f3f-b9e6-5dcbe1e33061@googlegroups.com>, Fred K <fred.l.kleinschmidt@gmail.com> wrote: [about xpm] > >Well, it was written a long time ago, and for platforms where the size >of an intwas the same size as a pointer. So far, I haven't found a >problem with iton an HP-UX, SGI, Sun, AIX; I'm now porting it to >several flavors of (64-bit) Linux, and iPad. Time will tell... Xpm isn't some dead artifact you just dug up that nobody else remembers. It has been continuously maintained and is still distributed by x.org. Why can't you use their version? It should already be bundled with your Linux distribution. -- Alan Curry


I just downloaded the current version (including source code) and it still has that code in it, so they are currently using code that may be problematic.
Reply With Quote
  #9 (permalink)  
Old 07-30-2012, 08:02 PM
Ben Bacarisse
Guest
 
Posts: n/a
Default Re: casting unsigned int to void*

Fred K <fred.l.kleinschmidt@gmail.com> writes:

> On Monday, July 30, 2012 11:46:51 AM UTC-7, Alan Curry wrote:
>> There was some really unforgivable formatting in here, especially the more deeply quoted parts, so I chopped them out. Google Groups sucks! Get a real newsreader! In article <afc78550-acc3-4f3f-b9e6-5dcbe1e33061@googlegroups.com>, Fred K <fred.l.kleinschmidt@gmail.com> wrote: [about xpm] > >Well, it was written a long time ago, and for platforms where the size >of an int was the same size as a pointer. So far, I haven't found a >problem with it on an HP-UX, SGI, Sun, AIX; I'm now porting it to >several flavors of (64-bit) Linux, and iPad. Time will tell... Xpm isn't some dead artifact you just dug up that nobody else remembers. It has been continuously maintained and is still distributed by x.org. Why can't you use their version? It should already be bundled with your Linux distribution. -- Alan Curry


There is something odd with your quoting! Is this another Google groups
issue?

> I just downloaded the current version (including source code) and it
> still has that code in it, so they are currently using code that may
> be problematic.


The "may" is key. It may be problematic, but I doubt it. It's a very
common trick, and every implementation I've used defines the conversion
in a way that makes recovery of the int (the actual purpose here) safe.

You are doing the porting, are you not? Is it actually a problem?

--
Ben.
Reply With Quote
  #10 (permalink)  
Old 07-30-2012, 08:04 PM
China Blue [Tor], Meersburg
Guest
 
Posts: n/a
Default Re: casting unsigned int to void*

In article <7edfdd82-a84a-4391-8a63-4a537668d4b7@googlegroups.com>,
Fred K <fred.l.kleinschmidt@gmail.com> 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. The intptr_t was eventually introduced to provide
an integer that would always be safe to hold addresses.

--
My name Indigo Montoya. | Die, Robbie Ferrier! Die!
You flamed my father. | I'm whoever you want me to be.
Prepare to be spanked. | Annoying Usenet one post at a time.
Stop posting that! | At least I can stay in character.
Reply With Quote
  #11 (permalink)  
Old 07-30-2012, 08:22 PM
James Kuyper
Guest
 
Posts: n/a
Default Re: casting unsigned int to void*

On 07/30/2012 04:04 PM, China Blue [Tor], Meersburg wrote:
....
> 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


Your descriptions seem highly platform-specific; I'm not familiar with a
platform that had those particular characteristics. Could you identify it?

> be 18 bits. The 80x86s had addresses (20 bits) larger than ints (16 bits),
> exposing this bad assumption. The intptr_t was eventually introduced to provide
> an integer that would always be safe to hold addresses.



Reply With Quote
  #12 (permalink)  
Old 07-30-2012, 09:55 PM
China Blue [Tor], Meersburg
Guest
 
Posts: n/a
Default Re: casting unsigned int to void*

In article <5016ECE9.3050605@verizon.net>,
James Kuyper <jameskuyper@verizon.net> wrote:

> On 07/30/2012 04:04 PM, China Blue [Tor], Meersburg wrote:
> ...
> > 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

>
> Your descriptions seem highly platform-specific; I'm not familiar with a
> platform that had those particular characteristics. Could you identify it?


http://en.wikipedia.org/wiki/CDC_6600

--
My name Indigo Montoya. | Die, Robbie Ferrier! Die!
You flamed my father. | I'm whoever you want me to be.
Prepare to be spanked. | Annoying Usenet one post at a time.
Stop posting that! | At least I can stay in character.
Reply With Quote
  #13 (permalink)  
Old 07-30-2012, 10:15 PM
James Kuyper
Guest
 
Posts: n/a
Default Re: casting unsigned int to void*

On 07/30/2012 05:55 PM, China Blue [Tor], Meersburg wrote:
> In article <5016ECE9.3050605@verizon.net>,
> James Kuyper <jameskuyper@verizon.net> wrote:
>
>> On 07/30/2012 04:04 PM, China Blue [Tor], Meersburg wrote:
>> ...
>>> 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

>>
>> Your descriptions seem highly platform-specific; I'm not familiar with a
>> platform that had those particular characteristics. Could you identify it?

>
> http://en.wikipedia.org/wiki/CDC_6600


Can you give us any particular reason to believe that this particular
processor had a major role to play in setting up expectations, relevant
to the design of C, that were later violated by the Intel 8086 family of
processors, as implied by your earlier message? Your wording gave the
impression that 60-bit integers were so widely used that many people
thought they were universal. The article you linked to refers to the
60-bit words as "very large", belying that implication.
Reply With Quote
  #14 (permalink)  
Old 07-30-2012, 10:18 PM
China Blue [Tor], Meersburg
Guest
 
Posts: n/a
Default Re: casting unsigned int to void*

In article <5017077F.7050601@verizon.net>,
James Kuyper <jameskuyper@verizon.net> wrote:

> On 07/30/2012 05:55 PM, China Blue [Tor], Meersburg wrote:
> > In article <5016ECE9.3050605@verizon.net>,
> > James Kuyper <jameskuyper@verizon.net> wrote:
> >
> >> On 07/30/2012 04:04 PM, China Blue [Tor], Meersburg wrote:
> >> ...
> >>> 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
> >>
> >> Your descriptions seem highly platform-specific; I'm not familiar with a
> >> platform that had those particular characteristics. Could you identify it?

> >
> > http://en.wikipedia.org/wiki/CDC_6600

>
> Can you give us any particular reason to believe that this particular
> processor had a major role to play in setting up expectations, relevant
> to the design of C, that were later violated by the Intel 8086 family of
> processors, as implied by your earlier message? Your wording gave the
> impression that 60-bit integers were so widely used that many people
> thought they were universal. The article you linked to refers to the
> 60-bit words as "very large", belying that implication.


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

--
My name Indigo Montoya. | Die, Robbie Ferrier! Die!
You flamed my father. | I'm whoever you want me to be.
Prepare to be spanked. | Annoying Usenet one post at a time.
Stop posting that! | At least I can stay in character.
Reply With Quote
  #15 (permalink)  
Old 07-30-2012, 10:36 PM
Ben Bacarisse
Guest
 
Posts: n/a
Default Re: casting unsigned int to void*

"China Blue [Tor], Meersburg" <chine.bleu@yahoo.com> writes:

> In article <7edfdd82-a84a-4391-8a63-4a537668d4b7@googlegroups.com>,
> Fred K <fred.l.kleinschmidt@gmail.com> 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
 
Reply

Thread Tools
Display Modes

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 Off
Pingbacks are Off
Refbacks are Off




All times are GMT. The time now is 10:45 PM.


Copyright ©2009

LinkBacks Enabled by vBSEO 3.3.0 RC2 © 2009, Crawlability, Inc.