Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   Typecasting Pointers on a 64 bit System (http://www.velocityreviews.com/forums/t805786-typecasting-pointers-on-a-64-bit-system.html)

Quentin Pope 11-10-2011 08:21 PM

Typecasting Pointers on a 64 bit System
 
What is the best way to handle this warning:

warning: cast from pointer to integer of different size

I am casting in and out of a function that requires a pointer type. I
am casting an integer as a pointer, but the pointer is 8 bytes while
the integer is only 4 bytes.

Here's an example function:

pthread_create(&tid, NULL, readit, (void *)(long)connfd)

I need to pass the file descriptor as a void * for pthread_create. But
I need the file descriptor as an integer to read and write to it. Is the
above the best approach to turn off the warning? I am considering just
typecasting to size_t before typecasting to the pointer. Is that a
better approach than typecasting to long since size_t should remain equal
to the size of pointers?

Of course, I run into the reverse problem when I have to close the
file descriptor.

close((int) arg);

I don't even know what to do in the above case. I shouldn't be
truncating anything, so I should be okay.

I originally wrote the code using a 32 bit version, so I am receiving
these errors when I ported it over to a 64 bit version.

Lauri Alanko 11-10-2011 08:29 PM

Re: Typecasting Pointers on a 64 bit System
 
In article <j9hbnp$13g$1@speranza.aioe.org>,
Quentin Pope <qp19433@hotmail.NOSPAM.com> wrote:
> pthread_create(&tid, NULL, readit, (void *)(long)connfd)
>
> I need to pass the file descriptor as a void * for pthread_create. But
> I need the file descriptor as an integer to read and write to it. Is the
> above the best approach to turn off the warning?


No.

Just pass a pointer to the fd:

pthread_create(&tid, NULL, readit, &connfd);

Then dereference the pointer in the readit function to get the
descriptor. If connfd is a local variable, you need to make sure that
connfd doesn't exit the scope before the new thread has read it. If
this is difficult, you can allocate a new copy for the thread:

int* fdp = malloc(sizeof(int));
*fdp = connfd;
pthread_create(&tid, NULL, readit, fdp);

void readit(void* fdp) {
int connfd = *(int*)fdp;
free(fdp);
...;
}


Lauri

Ben Pfaff 11-10-2011 08:32 PM

Re: Typecasting Pointers on a 64 bit System
 
Quentin Pope <qp19433@hotmail.NOSPAM.com> writes:

> What is the best way to handle this warning:
>
> warning: cast from pointer to integer of different size


The best way may be to avoid casting between a pointer and an
integer.

Another way is to use (u)intptr_t from <stdint.h>, which is
ordinarily defined as an integer type that is the same width as a
pointer.
--
Ben Pfaff
http://benpfaff.org

James Kuyper 11-10-2011 08:44 PM

Re: Typecasting Pointers on a 64 bit System
 
On 11/10/2011 03:32 PM, Ben Pfaff wrote:
....
> Another way is to use (u)intptr_t from <stdint.h>, which is
> ordinarily defined as an integer type that is the same width as a
> pointer.


More accurately, it's defined to be big enough for the conversion to be
reversible. In practice, it's likely to be the same size, but that's not
part of the definition. It could easily be larger. If there's any
redundancy in the pointer representation, and the conversion removes
that redundancy, it could even be smaller.

Kaz Kylheku 11-10-2011 08:45 PM

Re: Typecasting Pointers on a 64 bit System
 
On 2011-11-10, Quentin Pope <qp19433@hotmail.NOSPAM.com> wrote:
> What is the best way to handle this warning:
>
> warning: cast from pointer to integer of different size


Use an integer of a suitable size.

> I am casting in and out of a function that requires a pointer type. I
> am casting an integer as a pointer, but the pointer is 8 bytes while
> the integer is only 4 bytes.


In the C99 language, there is the intptr_t type for this sort of thing.

For older dialects of C, you have to cob together some kind of compile
time configuration. Define the type as a typedef and change it based
on target compiler and platform.

I've written a configure script which detects what integral type is
suitable for holding pointers (based on size) and throws the info
into a "config.h" header.

This is BSD licensed so you can borrow it.

http://www.kylheku.com/cgit/txr/tree/configure

The approach taken in this script is to compile a sample translation unit and
then inspect the symbols (using the POSIX-standard nm command).

This creates an int_ptr_t typedef in "config.h" along with macros
giving the minimum and maximum value.

It's only been tested on various GNU/Linux architectures, Cygwin and MinGW.

It supports cross-compiling because the test programs are only compiled, never
executed.

Kaz Kylheku 11-10-2011 08:51 PM

Re: Typecasting Pointers on a 64 bit System
 
On 2011-11-10, Lauri Alanko <la@iki.fi> wrote:
> In article <j9hbnp$13g$1@speranza.aioe.org>,
> Quentin Pope <qp19433@hotmail.NOSPAM.com> wrote:
>> pthread_create(&tid, NULL, readit, (void *)(long)connfd)
>>
>> I need to pass the file descriptor as a void * for pthread_create. But
>> I need the file descriptor as an integer to read and write to it. Is the
>> above the best approach to turn off the warning?

>
> No.
>
> Just pass a pointer to the fd:
>
> pthread_create(&tid, NULL, readit, &connfd);


Ths is an inferior approach because now the object &connfd has
to remain stable for as long as the created thread wants to touch
that object.

> Then dereference the pointer in the readit function to get the
> descriptor. If connfd is a local variable, you need to make sure that
> connfd doesn't exit the scope before the new thread has read it.


You need to ensure that AND that the object is not overwritten with a different
value (e.g. in a loop that launches more than one thread).

In this case, why use threads? Just call "readit" directly from
this thread.

If the parent thread has to be confined while a thread executes, there is no
point. Just thread creation and context switching overhead.

What you can do is implement some little "mousetrap" protocol
wherby the thread indicates "I have consumed the argument, you can
trash it now". E.g condition variable, etc.

Or you could just cast the darn value to a pointer!

> this is difficult, you can allocate a new copy for the thread:
>
> int* fdp = malloc(sizeof(int));
> *fdp = connfd;
> pthread_create(&tid, NULL, readit, fdp);


Or just cast the darn value to a pointer. Save this trick for when the argument
list grows to include more than one value.

Keith Thompson 11-10-2011 08:58 PM

Re: Typecasting Pointers on a 64 bit System
 
Ben Pfaff <blp@cs.stanford.edu> writes:
> Quentin Pope <qp19433@hotmail.NOSPAM.com> writes:
>> What is the best way to handle this warning:
>>
>> warning: cast from pointer to integer of different size

>
> The best way may be to avoid casting between a pointer and an
> integer.
>
> Another way is to use (u)intptr_t from <stdint.h>, which is
> ordinarily defined as an integer type that is the same width as a
> pointer.


But (u)intptr_t won't exist on systems where no integer type is
wide enough to hold a converted pointer value without loss of
information, so code that depends on it is non-portable. But if
you insist on passing an integer value in a pointer argument,
uintptr_t or intptr_t is the way to go.

In this case, the intent of the "arg" argument to pthread_create()
is that it should be a pointer to data needed by the start routine.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Kaz Kylheku 11-10-2011 08:58 PM

Re: Typecasting Pointers on a 64 bit System
 
On 2011-11-10, Kaz Kylheku <kaz@kylheku.com> wrote:
> On 2011-11-10, Lauri Alanko <la@iki.fi> wrote:
>> int* fdp = malloc(sizeof(int));
>> *fdp = connfd;
>> pthread_create(&tid, NULL, readit, fdp);

>
> Or just cast the darn value to a pointer. Save this trick for when the argument
> list grows to include more than one value.


P.S. what is more important: having an allergic reaction to
pointer-integer casts? Or checking the return value of malloc.

:)

Kaz Kylheku 11-10-2011 09:00 PM

Re: Typecasting Pointers on a 64 bit System
 
On 2011-11-10, Kaz Kylheku <kaz@kylheku.com> wrote:
> On 2011-11-10, Quentin Pope <qp19433@hotmail.NOSPAM.com> wrote:
>> What is the best way to handle this warning:
>>
>> warning: cast from pointer to integer of different size

>
> Use an integer of a suitable size.
>
>> I am casting in and out of a function that requires a pointer type. I
>> am casting an integer as a pointer, but the pointer is 8 bytes while
>> the integer is only 4 bytes.

>
> In the C99 language, there is the intptr_t type for this sort of thing.
>
> For older dialects of C, you have to cob together some kind of compile
> time configuration. Define the type as a typedef and change it based
> on target compiler and platform.
>
> I've written a configure script which detects what integral type is
> suitable for holding pointers (based on size) and throws the info
> into a "config.h" header.


But, by the way, I would not bother with this for something so trivial.

Here, your pointer type is larger than the integer you are trying to
pass through, so it doesn't matter.

Just kill the warning for that source file.

James Kuyper 11-10-2011 09:08 PM

Re: Typecasting Pointers on a 64 bit System
 
On 11/10/2011 03:51 PM, Kaz Kylheku wrote:
> On 2011-11-10, Lauri Alanko <la@iki.fi> wrote:
>> In article <j9hbnp$13g$1@speranza.aioe.org>,
>> Quentin Pope <qp19433@hotmail.NOSPAM.com> wrote:
>>> pthread_create(&tid, NULL, readit, (void *)(long)connfd)
>>>
>>> I need to pass the file descriptor as a void * for pthread_create. But
>>> I need the file descriptor as an integer to read and write to it. Is the
>>> above the best approach to turn off the warning?

>>
>> No.
>>
>> Just pass a pointer to the fd:
>>
>> pthread_create(&tid, NULL, readit, &connfd);

>
> Ths is an inferior approach because now the object &connfd has
> to remain stable for as long as the created thread wants to touch
> that object.
>
>> Then dereference the pointer in the readit function to get the
>> descriptor. If connfd is a local variable, you need to make sure that
>> connfd doesn't exit the scope before the new thread has read it.

....
> Or you could just cast the darn value to a pointer!


Unless you're worried about the possibility that the result of the
conversion is a trap representation, as is explicitly allowed by the C
standard. Does POSIX say something to guarantee that this is not a
possibility?


All times are GMT. The time now is 01:39 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.