Typecasting Pointers on a 64 bit System

Discussion in 'C Programming' started by bwaichu@yahoo.com, Aug 8, 2006.

  1. Guest

    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.

    Thanks!
     
    , Aug 8, 2006
    #1
    1. Advertising

  2. Ian Collins Guest

    wrote:
    > 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)
    >

    Why cast rather than simply pass the address of the int?

    --
    Ian Collins.
     
    Ian Collins, Aug 8, 2006
    #2
    1. Advertising

  3. Dann Corbit Guest

    <> wrote in message
    news:...
    > 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.


    If your pointer is 8 bytes and your integer is 4 bytes, then it is
    physically impossible for the mapping to be one to one and onto. (Which is
    another way of saying that such a transfer is clearly not reversible,
    because you have lost one half of your address).

    You may be able to store the pointer in a long long, but why not store it in
    another pointer [preferably of the same type]? Another possibility is to
    store it in a character string either by sprintf() for a human readable
    version or by memcpy() into an array that is sizeof (void *) bytes long.

    Aside:
    You can't cram 8 pounds of hamburger into a 4 pound can. You'll have 4
    pounds of burger on the floor. But if you can decompile it back into the
    cow, you might have an interesting conversation starter.
     
    Dann Corbit, Aug 8, 2006
    #3
  4. Eric Sosman Guest

    wrote:

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


    Best way: Don't Do That. Pointers are not integers, and
    integers are not pointers, and trying to pretend they are the
    same is not smart.

    > 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.


    You are doing something that is not a good idea. Stop.

    > 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?


    Pass a pointer to the integer variable:

    pthread_create(..., &connfd);

    > Of course, I run into the reverse problem when I have to close the
    > file descriptor.
    >
    > close((int) arg);


    ... and on the other end (threads are off-topic here, but
    we'll let that pass), convert the void* back to an int* and
    use it to retrieve the actual int value:

    close (* (int*)arg );

    Note that the conversion of int* to void* and back to int*
    again is a completely different matter from what you've been
    trying. This pointer-to-pointer conversion is well-defined;
    the pointer-integer-pointer conversion is not.

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


    Yes, of course: You're perfectly okay. That's why the
    compiler is applauding your attempt. ;-)

    > 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.


    It was bad even in thirty-two bits. Now it's worse.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Aug 8, 2006
    #4
  5. Chris Torek Guest

    In article <>
    <> wrote:
    >pthread_create(&tid, NULL, readit, (void *)(long)connfd)


    (where the fourth argument to pthread_create() has type "void *",
    and "connfd" is an "int")

    >I need to pass the file descriptor as a void * for pthread_create.


    Well, not quite. You do need to pass a "void *" -- but there is
    nothing that says you have to take the "int" value, convert it
    to "void *", and then pass that. You can, instead, pass the
    address of a data structure that includes the desired "int"
    value.

    For instance:

    struct data_to_pass_via_pthread_create {
    int this;
    double that;
    long the_other;
    int connfd;
    };
    ...
    struct data_to_pass_via_pthread_create x;
    x.connfd = connfd;
    ...
    result = pthread_create(&tid, NULL, readit, &x);
    ...

    If the only data item you want to pass is "connfd" itself, just
    ues &connfd instead of setting up some object "x" and using &x.

    Note that the lifetime (i.e., storage duration) of the variable
    you pass via this pointer needs to be sufficiently great so that
    wherever you access the pointer -- presumably in a POSIX thread,
    about which we in comp.lang.c cannot know anything :) -- that
    pointer is still valid. (What this really means is that, because
    POSIX threads do funny stack manipulation, using "auto" variables
    is sometimes suspect -- you may have to use "static" variables
    or use malloc() to get sufficient lifetimes.)

    (When you used the "sleazy hack" of converting the integer directly
    to (void *) via cast, and then back via another cast, in the 32-bit
    version, you avoided the need to make sure that the object to which
    the pointer points remained valid, because the pointer did not in
    fact point to any object. When you switch to the "fully portable"
    method of passing the address of an object, the lifetime of the
    object starts to matter.)
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.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.
     
    Chris Torek, Aug 8, 2006
    #5
  6. Guest

    Thanks.

    This worked a whole lot better:

    close(*(int *)arg);

    Thanks alot! And just passing the address of the file descriptor
    worked out great.

    Brian

    Note: I knew this was bad to start with it. But I had overlooked the
    obvious pointer to
    pointer conversion since I did not receive any warnings on the
    32 bit OS. Also,
    my question had absolutely nothing to do with threads. It
    just happened to be
    the scenario that was causing me to see warnings pop up when I
    compiled on my 64
    bit OS.
     
    , Aug 8, 2006
    #6
  7. Guest

    Chris Torek wrote:

    > (When you used the "sleazy hack" of converting the integer directly
    > to (void *) via cast, and then back via another cast, in the 32-bit
    > version, you avoided the need to make sure that the object to which
    > the pointer points remained valid, because the pointer did not in
    > fact point to any object. When you switch to the "fully portable"
    > method of passing the address of an object, the lifetime of the
    > object starts to matter.)


    And I wanted to fix the above problem before proceeding to write code
    that parses the string that I read in that thread.

    Here's a compiler specific question:

    Is there any gcc compiler flag I can use that would have warned me
    about this on my 32 bit OS? (I am currently using -O -Wall -pedantic
    -ansi -pthread; C99 as far as I know isn't fully supported on gcc
    3.3.5.)

    Now, back to C specific questions:

    What would cause me to lose the object? At this point I am only
    passing a file descriptor, but I can foresee in the future passing
    structures as I work through this little program.

    Thanks,

    Brian
     
    , Aug 8, 2006
    #7
  8. said:

    <snip>
    >
    > Is there any gcc compiler flag I can use that would have warned me
    > about this on my 32 bit OS?


    Very unlikely.

    When you cast, you're saying to the compiler, "trust me, I know what I'm
    doing, I won't hurt you, it'll be all right"; and the compiler looks
    lovingly into your eyes, and *believes* you - even when it does actually
    hurt quite a bit - and doesn't say a word.

    Most of the time, alas, the compiler's trust is misplaced, because most of
    the time the programmer is untrustworthy, and doesn't know what he's doing.
    And it most certainly won't be all right.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
     
    Richard Heathfield, Aug 8, 2006
    #8
  9. Eric Sosman Guest

    wrote:

    > Thanks.
    >
    > This worked a whole lot better:
    >
    > close(*(int *)arg);
    >
    > Thanks alot! And just passing the address of the file descriptor
    > worked out great.
    >
    > Brian
    >
    > Note: I knew this was bad to start with it. But I had overlooked the
    > obvious pointer to
    > pointer conversion since I did not receive any warnings on the
    > 32 bit OS. Also,
    > my question had absolutely nothing to do with threads. It
    > just happened to be
    > the scenario that was causing me to see warnings pop up when I
    > compiled on my 64
    > bit OS.
    >


    <off-topic>

    One cautionary note: Whenever you pass a pointer to an
    asynchronously-executing thread -- at thread creation or at
    any other time -- you must take care that the pointer will
    remain valid until the thread has finished using it. In your
    case, if `connfd' is a local variable in the "launcher"
    function, it will cease to exist when that function returns.
    If you passed `&connfd' to the newly-created thread, it will
    find itself trying to use a pointer to a variable that has
    been destroyed, and whose memory may have been overwritten by
    other variables ...

    More on this at comp.programming.threads.

    </off-topic>

    --
    Eric Sosman
    lid
     
    Eric Sosman, Aug 8, 2006
    #9
  10. Guest

    Richard Heathfield wrote:

    >
    > When you cast, you're saying to the compiler, "trust me, I know what I'm
    > doing, I won't hurt you, it'll be all right"; and the compiler looks
    > lovingly into your eyes, and *believes* you - even when it does actually
    > hurt quite a bit - and doesn't say a word.
    >
    > Most of the time, alas, the compiler's trust is misplaced, because most of
    > the time the programmer is untrustworthy, and doesn't know what he's doing.
    > And it most certainly won't be all right.


    Can I simply just apply a rule of thumb not to cast pointers to
    non-pointers and vice versa? Or is there actually a right way to cast
    pointers to non-pointers and vice versa?
     
    , Aug 8, 2006
    #10
  11. said:

    <snip>

    > Can I simply just apply a rule of thumb not to cast pointers to
    > non-pointers and vice versa?


    A (valid) pointer value is the address of an object or function. This might
    be something like:

    29059400
    534277878593578937890000
    DS:0A00
    GRP9J14

    It's easy to see how the first can be interpreted as an int. The second? A
    bit harder, since we're running up against possible implementation limits.
    The third? A bit trickier still - what would "DS:" /mean/ as an integer?
    The fourth? Surely impossible.

    A standard C program that /could/ cast meaningfully from a pointer to an
    integer would, therefore, have to be capable of doing the impossible.

    > Or is there actually a right way to cast
    > pointers to non-pointers and vice versa?


    If you have to do it, use a cast. For example:

    unsigned long foo = (unsigned long)p; /* but does foo have enough bits? */

    Better still: Just Don't Do That. Or at least, if you really really have to
    do it, be aware that it has no portable semantics, and so you should
    isolate it, along with your other non-portable code, into
    easily-identifiable bits that you can rewrite for each targeted platform.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
     
    Richard Heathfield, Aug 8, 2006
    #11
  12. On Tue, 8 Aug 2006 02:58:45 UTC, ""
    <> wrote:

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


    Fix up the code. There is no need to cast pointer to int or int to
    pointer. Even when in your environment they may have the same bitwidth
    you may end up in undefined behavior.

    > 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.


    When the fuction requires a pointer give it one. casting something to
    a pointer is not a solution but a first range of source for undefined
    behavior.

    > 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.


    Untrue. You need to pass a pointer to a file descriptor.

    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?


    The best is to pass a pointer to the variable holding the value.

    > Of course, I run into the reverse problem when I have to close the
    > file descriptor.
    >
    > close((int) arg);


    Having the pointer to the descriptor here by hand you had anything you
    needs.

    > 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.


    Pass pointers when a pointer is required. Pass values when values are
    required.

    Hint: Since C89 you can always pass a pointer to data of any type when
    a pointer to void is required. You can use the magic conversion to
    compiler gives you to convert a pointer to void to the originam
    pointer type without casting.

    Attention: be sure that you never tries to pass a pointer to an auto
    variable.

    Hint: whenever you have to create a new thread and pass it its own
    variables uses malloc to create a struct holding all variables you
    have to pass and pass simply the pointer you got from malloc. Let the
    thread free() that pointer when it has no need to use the data
    therein. For that the last parameter of pthreads() is designed, not to
    pass something that is not a pointer.

    So it doesn't matter if your system is 16, 32, 48, 64 or 123 bits
    wide.

    Yeah, it will be a lot of work to rewrite the 32 bit app to get it -
    but have it done it will work in 64 bit too without a change, making
    maintenance a lot easier.

    --
    Tschau/Bye
    Herbert

    Visit http://www.ecomstation.de the home of german eComStation
    eComStation 1.2 Deutsch ist da!
     
    Herbert Rosenau, Aug 8, 2006
    #12
  13. "Eric Sosman" <> wrote in message
    news:D...
    > wrote:
    >> This worked a whole lot better:
    >>
    >> close(*(int *)arg);
    >>
    >> Thanks alot! And just passing the address of the file descriptor
    >> worked out great.

    >
    > <off-topic>
    >
    > One cautionary note: Whenever you pass a pointer to an
    > asynchronously-executing thread -- at thread creation or at
    > any other time -- you must take care that the pointer will
    > remain valid until the thread has finished using it. In your
    > case, if `connfd' is a local variable in the "launcher"
    > function, it will cease to exist when that function returns.
    > If you passed `&connfd' to the newly-created thread, it will
    > find itself trying to use a pointer to a variable that has
    > been destroyed, and whose memory may have been overwritten by
    > other variables ...
    >
    > More on this at comp.programming.threads.
    >
    > </off-topic>


    <OT>

    When I do things like this, I malloc() an int and have the worker
    thread free() it. That avoids doing things like:

    int i = 1;
    pthread_create(&tid, NULL, func, &i);
    i = 2;
    pthread_create(&tid, NULL, func, &i);
    i = 3;
    pthread_create(&tid, NULL, func, &i);

    (Imagine that in a loop, where someone might not catch the
    modification before use)

    It also conveniently avoids the case where the int goes out of scope
    (in the parent thread) before the worker thread is done with it.

    </OT>

    S

    --
    Stephen Sprunk "God does not play dice." --Albert Einstein
    CCIE #3723 "God is an inveterate gambler, and He throws the
    K5SSS dice at every possible opportunity." --Stephen Hawking



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    Stephen Sprunk, Aug 8, 2006
    #13
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. brian

    Typecasting Pointers

    brian, Nov 23, 2004, in forum: C Programming
    Replies:
    13
    Views:
    1,275
    Michael Wojcik
    Nov 29, 2004
  2. Replies:
    3
    Views:
    594
    Emmanuel Delahaye
    Jul 15, 2005
  3. typecasting of function pointers

    , Mar 20, 2006, in forum: C Programming
    Replies:
    12
    Views:
    926
    Flash Gordon
    Mar 21, 2006
  4. Quentin Pope

    Typecasting Pointers on a 64 bit System

    Quentin Pope, Nov 10, 2011, in forum: C Programming
    Replies:
    54
    Views:
    1,540
    Phil Carmody
    Nov 18, 2011
  5. David Filmer
    Replies:
    14
    Views:
    189
    Peter J. Holzer
    Aug 8, 2010
Loading...

Share This Page