reinterpret cast problem.

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Dave Townsend

    reinterpret cast problem.

    Hi,

    I'm trying to port a piece of code from Windows to Linux, the following
    segment illustrates the coding problemI have: Under Linux, the
    reinterpret_cas t line
    doesn't compile, the compiler says ISO C++ doesn allow a cast from
    pointer-to-object
    to pointer-to-function. However, I can use the plain-old-C-style cast and
    the code compiles and works. I guess I have two questions:-

    1. What is the sanctified way to write this type of code.
    2. What is the rational behind the GNU compiler message ( presuming the
    compiler is correctly interpreting the standard).

    Thanks,

    dave.

    #include <stdio.h>

    static int foo()
    {
    printf("hello\n ");
    return 0;
    }

    typedef int fnc_t();

    int main(int argc, char* argv[])
    {
    void* fv = (fnc_t*)foo;

    fnc_t* fnc = reinterpret_cas t<fnc_t*>(fv); // illegal under GNU/linux

    fnc();


    return 0;
    }


  • Ivan Vecerina

    #2
    Re: reinterpret cast problem.

    "Dave Townsend" <datownsend@com cast.net> wrote in message
    news:qNOdnT8bO8 Qld4_fRVn-rA@comcast.com. ..[color=blue]
    > I'm trying to port a piece of code from Windows to Linux, the following
    > segment illustrates the coding problemI have: Under Linux, the
    > reinterpret_cas t line
    > doesn't compile, the compiler says ISO C++ doesn allow a cast from
    > pointer-to-object
    > to pointer-to-function. However, I can use the plain-old-C-style cast and
    > the code compiles and works. I guess I have two questions:-
    >
    > 1. What is the sanctified way to write this type of code.[/color]

    Just as 'void*' can be used to store the address of any object, 'void (*)()'
    can store the address of any function pointer.
    typedef void (*voidF)();
    You can safely cast any function pointer to voidF and back.
    [color=blue]
    > 2. What is the rational behind the GNU compiler message ( presuming the
    > compiler is correctly interpreting the standard).[/color]

    Does the reinterpret_cas t generate a warning or an error?
    I'm not sure it should be an error, but it sure is a valid warning:
    it is formally not portable to convert a function pointer to void*
    and back (even though current platforms typically use a common
    address space and register set for both data and code).


    I hope this helps,
    Ivan
    --
    http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form


    Comment

    • Jonathan Turkanis

      #3
      Re: reinterpret cast problem.

      Dave Townsend wrote:[color=blue]
      > Hi,
      >
      > I'm trying to port a piece of code from Windows to Linux, the
      > following segment illustrates the coding problemI have: Under Linux,
      > the reinterpret_cas t line
      > doesn't compile, the compiler says ISO C++ doesn allow a cast from
      > pointer-to-object
      > to pointer-to-function. However, I can use the plain-old-C-style
      > cast and the code compiles and works. I guess I have two questions:-[/color]

      First, there are a number of compilers available for Windows and Linux. I gather
      you're using GCC, but it wouldn't hurt to mention it. Also, the version is often
      useful.
      [color=blue]
      > 1. What is the sanctified way to write this type of code.
      > 2. What is the rational behind the GNU compiler message ( presuming
      > the compiler is correctly interpreting the standard).
      >
      > Thanks,
      >
      > dave.
      >
      > #include <stdio.h>
      >
      > static int foo()
      > {
      > printf("hello\n ");
      > return 0;
      > }
      >
      > typedef int fnc_t();
      >
      > int main(int argc, char* argv[])
      > {
      > void* fv = (fnc_t*)foo;
      >
      > fnc_t* fnc = reinterpret_cas t<fnc_t*>(fv); // illegal under
      > GNU/linux
      >
      > fnc();
      >
      >
      > return 0;
      > }[/color]

      GCC is correct. You can't reinterpret_cas t between pointers to objects and
      pointers to functions. If you need to be able to store either a function pointer
      or an object pointer in a single variable, you can use a union:

      union any_pointer
      {
      void* obj_ptr;
      void (*func_ptr)();
      };

      Jonathan


      Comment

      • Jonathan Turkanis

        #4
        Re: reinterpret cast problem.

        Jonathan Turkanis wrote:
        [color=blue]
        > First, there are a number of compilers available for Windows and
        > Linux. I gather you're using GCC,[/color]

        on Linux, I mean
        [color=blue]
        > but it wouldn't hurt to mention it.
        > Also, the version is often useful.[/color]


        Comment

        • Ioannis Vranos

          #5
          Re: reinterpret cast problem.

          Dave Townsend wrote:
          [color=blue]
          > Hi,
          >
          > I'm trying to port a piece of code from Windows to Linux, the following
          > segment illustrates the coding problemI have: Under Linux, the
          > reinterpret_cas t line
          > doesn't compile, the compiler says ISO C++ doesn allow a cast from
          > pointer-to-object
          > to pointer-to-function.[/color]


          It doesn't compile under Windows with gcc either:

          C:\c>g++ temp.cpp -o temp.exe
          temp.cpp: In function `int main(int, char**)':
          temp.cpp:13: error: invalid conversion from `int (*)()' to `void*'
          temp.cpp:15: error: ISO C++ forbids casting between pointer-to-function and
          pointer-to-object
          temp.cpp:21:2: warning: no newline at end of file

          C:\c>


          [color=blue]
          > However, I can use the plain-old-C-style cast and
          > the code compiles and works. I guess I have two questions:-
          >
          > 1. What is the sanctified way to write this type of code.
          > 2. What is the rational behind the GNU compiler message ( presuming the
          > compiler is correctly interpreting the standard).
          >
          > Thanks,
          >
          > dave.
          >
          > #include <stdio.h>
          >
          > static int foo()
          > {
          > printf("hello\n ");
          > return 0;
          > }
          >
          > typedef int fnc_t();
          >
          > int main(int argc, char* argv[])
          > {
          > void* fv = (fnc_t*)foo;
          >
          > fnc_t* fnc = reinterpret_cas t<fnc_t*>(fv); // illegal under GNU/linux
          >
          > fnc();
          >
          >
          > return 0;
          > }[/color]



          Others have provided explanations for the rest. The above would be
          better if it was:


          #include <iostream>

          namespace
          {
          int foo()
          {
          std::cout<<"hel lo\n";

          return 0;
          }
          }

          typedef int fnc_t();


          int main()
          {

          fnc_t *fnc = foo;

          fnc();


          return 0;
          }




          --
          Ioannis Vranos


          Comment

          • Jack Klein

            #6
            Re: reinterpret cast problem.

            On Tue, 15 Feb 2005 22:39:49 -0800, "Dave Townsend"
            <datownsend@com cast.net> wrote in comp.lang.c++:
            [color=blue]
            > Hi,
            >
            > I'm trying to port a piece of code from Windows to Linux, the following
            > segment illustrates the coding problemI have: Under Linux, the
            > reinterpret_cas t line
            > doesn't compile, the compiler says ISO C++ doesn allow a cast from
            > pointer-to-object
            > to pointer-to-function. However, I can use the plain-old-C-style cast and
            > the code compiles and works. I guess I have two questions:-
            >
            > 1. What is the sanctified way to write this type of code.[/color]

            There isn't any. There is absolutely no defined conversion between a
            pointer to any type of object and a pointer to any type of function.
            Not in either C or C++.

            And in fact there are implementations where such conversions are
            literally impossible, as pointers to functions are wider than pointers
            to any type of object. Bits are truncated and there is no way to get
            them back.
            [color=blue]
            > 2. What is the rational behind the GNU compiler message ( presuming the
            > compiler is correctly interpreting the standard).[/color]

            The rational is that in C++, as inherited from C, there are objects
            and there are functions. They are apples and oranges, they do not
            mix. In either language, conversion of a pointer to function to a
            pointer to object, in either direction, with or without a cast, is
            completely undefined.

            The real problem is sloppy interfaces, both in Windows and *nix, where
            they use a pointer to void to hold pointers to functions. This is not
            and never has been defined behavior. A union of two pointers could
            have been used with no runtime overhead in either execution time or
            space on implementations where the two types are the same size, but
            it's probably too late now.
            [color=blue]
            > Thanks,
            >
            > dave.
            >
            > #include <stdio.h>
            >
            > static int foo()
            > {
            > printf("hello\n ");
            > return 0;
            > }
            >
            > typedef int fnc_t();
            >
            > int main(int argc, char* argv[])
            > {
            > void* fv = (fnc_t*)foo;
            >
            > fnc_t* fnc = reinterpret_cas t<fnc_t*>(fv); // illegal under GNU/linux[/color]

            Actually, it's illegal under any compiler. But since it's undefined
            behavior, no diagnostic is required.
            [color=blue]
            > fnc();
            >
            >
            > return 0;
            > }[/color]

            --
            Jack Klein
            Home: http://JK-Technology.Com
            FAQs for
            comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
            comp.lang.c++ http://www.parashift.com/c++-faq-lite/
            alt.comp.lang.l earn.c-c++

            Comment

            Working...