Typecasting Pointers on a 64 bit System

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • bwaichu@yahoo.com

    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.

    Thanks!

  • Ian Collins

    #2
    Re: Typecasting Pointers on a 64 bit System

    bwaichu@yahoo.c om 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.

    Comment

    • Dann Corbit

      #3
      Re: Typecasting Pointers on a 64 bit System

      <bwaichu@yahoo. comwrote in message
      news:1155005925 .251571.129910@ p79g2000cwp.goo glegroups.com.. .
      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.


      Comment

      • Eric Sosman

        #4
        Re: Typecasting Pointers on a 64 bit System

        bwaichu@yahoo.c om 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
        esosman@acm-dot-org.invalid

        Comment

        • bwaichu@yahoo.com

          #5
          Re: Typecasting Pointers on a 64 bit System


          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.

          Comment

          • Chris Torek

            #6
            Re: Typecasting Pointers on a 64 bit System

            In article <1155005925.251 571.129910@p79g 2000cwp.googleg roups.com>
            bwaichu@yahoo.c om <bwaichu@yahoo. comwrote:
            >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_vi a_pthread_creat e {
            int this;
            double that;
            long the_other;
            int connfd;
            };
            ...
            struct data_to_pass_vi a_pthread_creat e 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.

            Comment

            • bwaichu@yahoo.com

              #7
              Re: Typecasting Pointers on a 64 bit System


              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

              Comment

              • Richard Heathfield

                #8
                Re: Typecasting Pointers on a 64 bit System

                bwaichu@yahoo.c om 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

                email: rjh at above domain (but drop the www, obviously)

                Comment

                • Eric Sosman

                  #9
                  Re: Typecasting Pointers on a 64 bit System

                  bwaichu@yahoo.c om 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.programmin g.threads.

                  </off-topic>

                  --
                  Eric Sosman
                  esosman@acm-dot-org.invalid

                  Comment

                  • bwaichu@yahoo.com

                    #10
                    Re: Typecasting Pointers on a 64 bit System


                    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?

                    Comment

                    • Richard Heathfield

                      #11
                      Re: Typecasting Pointers on a 64 bit System

                      bwaichu@yahoo.c om 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
                      534277878593578 937890000
                      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

                      email: rjh at above domain (but drop the www, obviously)

                      Comment

                      • Herbert Rosenau

                        #12
                        Re: Typecasting Pointers on a 64 bit System

                        On Tue, 8 Aug 2006 02:58:45 UTC, "bwaichu@yahoo. com"
                        <bwaichu@yahoo. comwrote:
                        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!

                        Comment

                        • Stephen Sprunk

                          #13
                          Re: Typecasting Pointers on a 64 bit System

                          "Eric Sosman" <esosman@acm-dot-org.invalidwrot e in message
                          news:D6mdncvTfe Ll6kXZnZ2dnUVZ_ r2dnZ2d@comcast .com...
                          bwaichu@yahoo.c om 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.programmin g.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

                          Comment

                          Working...