Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. [Challenge/Puzzle] Implement reinterpret_cast

[Challenge/Puzzle] Implement reinterpret_cast

Scheduled Pinned Locked Moved C / C++ / MFC
c++json
17 Posts 5 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    MicroVirus
    wrote on last edited by
    #1

    Hey coders, I came up with a little puzzle/challenge for C++, so for those interested, my challenge to you is this: Using any C++ constructs, other than any of the casting constructs*, reimplement the following code:

    int i = someIntValue();
    int *pint = reinterpret_cast(i)

    Or in words, find a way to reinterpret_cast an integer into a pointer without casting (implicitly, or explicitly!). You may assume that sizeof(int)==sizeof(int*). I hope to be surprised by answers I hadn't thought of :) * with casting constructs, I mean any form of implicit casts (e.g. int to long int), C-style casts (e.g. (int*)i) and C++-style casts (e.g. reinterpet_cast(i)); and also any functions/macro's/API calls (such as STL implementations) which rely internally on casts. Best Regards, Richard

    L M S 4 Replies Last reply
    0
    • M MicroVirus

      Hey coders, I came up with a little puzzle/challenge for C++, so for those interested, my challenge to you is this: Using any C++ constructs, other than any of the casting constructs*, reimplement the following code:

      int i = someIntValue();
      int *pint = reinterpret_cast(i)

      Or in words, find a way to reinterpret_cast an integer into a pointer without casting (implicitly, or explicitly!). You may assume that sizeof(int)==sizeof(int*). I hope to be surprised by answers I hadn't thought of :) * with casting constructs, I mean any form of implicit casts (e.g. int to long int), C-style casts (e.g. (int*)i) and C++-style casts (e.g. reinterpet_cast(i)); and also any functions/macro's/API calls (such as STL implementations) which rely internally on casts. Best Regards, Richard

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      This forum is for serious questions, the Lounge is the place for quizzes.

      Use the best guess

      M B 2 Replies Last reply
      0
      • L Lost User

        This forum is for serious questions, the Lounge is the place for quizzes.

        Use the best guess

        M Offline
        M Offline
        MicroVirus
        wrote on last edited by
        #3

        Hmmm :rolleyes: Didn't realise that. I felt it was more in place in a C++ specific message board than in a lounge, as I do find such challenges to be stimulating myself.

        1 Reply Last reply
        0
        • L Lost User

          This forum is for serious questions, the Lounge is the place for quizzes.

          Use the best guess

          B Offline
          B Offline
          Brandon X12000
          wrote on last edited by
          #4

          Richard MacCutchan wrote:

          This forum is for serious questions, the Lounge is the place for quizzes.

          I deem this is technically appropriate (by the definitions of the rules), it is C++/C code. Where in the rules up at the very top posted by Admin Chris Maunder, does it directly say that is for serious questions. Keep in mind a quiz is a question, you are giving an answer. EDIT:

          Chris Maunder wrote:

          Please do not post links to your question in one forum from another, unrelated forum (such as the lounge). It will be deleted.

          And you said...

          Richard MacCutchan wrote:

          the Lounge is the place for quizzes.

          Trying to guide him in the wrong path ;) , consider re-reading the rules.

          Simple Thanks and Regards, Brandon T. H. Programming in C and C++ now, now developing applications, services and drivers (and maybe some kernel modules...psst kernel-mode drivers...psst). Many of life's failures are people who did not realize how close they were to success when they gave up. - Thomas Edison

          L 1 Reply Last reply
          0
          • B Brandon X12000

            Richard MacCutchan wrote:

            This forum is for serious questions, the Lounge is the place for quizzes.

            I deem this is technically appropriate (by the definitions of the rules), it is C++/C code. Where in the rules up at the very top posted by Admin Chris Maunder, does it directly say that is for serious questions. Keep in mind a quiz is a question, you are giving an answer. EDIT:

            Chris Maunder wrote:

            Please do not post links to your question in one forum from another, unrelated forum (such as the lounge). It will be deleted.

            And you said...

            Richard MacCutchan wrote:

            the Lounge is the place for quizzes.

            Trying to guide him in the wrong path ;) , consider re-reading the rules.

            Simple Thanks and Regards, Brandon T. H. Programming in C and C++ now, now developing applications, services and drivers (and maybe some kernel modules...psst kernel-mode drivers...psst). Many of life's failures are people who did not realize how close they were to success when they gave up. - Thomas Edison

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #5

            Brandon-X12000 wrote:

            I deem this is technically appropriate

            I suspect you are in a minority.

            Brandon-X12000 wrote:

            Trying to guide him in the wrong path

            Not at all, the Lounge is the place for such questions; even Chris posts them there.

            Use the best guess

            1 Reply Last reply
            0
            • M MicroVirus

              Hey coders, I came up with a little puzzle/challenge for C++, so for those interested, my challenge to you is this: Using any C++ constructs, other than any of the casting constructs*, reimplement the following code:

              int i = someIntValue();
              int *pint = reinterpret_cast(i)

              Or in words, find a way to reinterpret_cast an integer into a pointer without casting (implicitly, or explicitly!). You may assume that sizeof(int)==sizeof(int*). I hope to be surprised by answers I hadn't thought of :) * with casting constructs, I mean any form of implicit casts (e.g. int to long int), C-style casts (e.g. (int*)i) and C++-style casts (e.g. reinterpet_cast(i)); and also any functions/macro's/API calls (such as STL implementations) which rely internally on casts. Best Regards, Richard

              M Offline
              M Offline
              Matthew Faithfull
              wrote on last edited by
              #6

              You could do something like:-

              int i = 42;
              int* pint = 0;
              int** ppint = 0;
              ppint += &i;
              pint = *ppint;

              If I'm not mistaken pint is now an int pointer to address 42 and no casting as such has taken place.

              "The secret of happiness is freedom, and the secret of freedom, courage." Thucydides (B.C. 460-400)

              S 1 Reply Last reply
              0
              • M MicroVirus

                Hey coders, I came up with a little puzzle/challenge for C++, so for those interested, my challenge to you is this: Using any C++ constructs, other than any of the casting constructs*, reimplement the following code:

                int i = someIntValue();
                int *pint = reinterpret_cast(i)

                Or in words, find a way to reinterpret_cast an integer into a pointer without casting (implicitly, or explicitly!). You may assume that sizeof(int)==sizeof(int*). I hope to be surprised by answers I hadn't thought of :) * with casting constructs, I mean any form of implicit casts (e.g. int to long int), C-style casts (e.g. (int*)i) and C++-style casts (e.g. reinterpet_cast(i)); and also any functions/macro's/API calls (such as STL implementations) which rely internally on casts. Best Regards, Richard

                S Offline
                S Offline
                Stefan_Lang
                wrote on last edited by
                #7

                int i = someIntValue();
                int *pint = 0;
                pint += i;

                Note that this doesn't even require sizeof(int)==sizeof(int*), as i will be cast to the correct size implicitely.

                L 1 Reply Last reply
                0
                • S Stefan_Lang

                  int i = someIntValue();
                  int *pint = 0;
                  pint += i;

                  Note that this doesn't even require sizeof(int)==sizeof(int*), as i will be cast to the correct size implicitely.

                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #8

                  But it will also be multiplied by sizeof(int) implicitly.. And if you divide by sizeof(int) first, it kills the lowest bit(s).

                  S 1 Reply Last reply
                  0
                  • L Lost User

                    But it will also be multiplied by sizeof(int) implicitly.. And if you divide by sizeof(int) first, it kills the lowest bit(s).

                    S Offline
                    S Offline
                    Stefan_Lang
                    wrote on last edited by
                    #9

                    Ah, you're right on both accounts. Not that it would make much sense to have an incorrectly aligned pointer, but then the challenge didn't make much sense for practical use anyway...

                    1 Reply Last reply
                    0
                    • M Matthew Faithfull

                      You could do something like:-

                      int i = 42;
                      int* pint = 0;
                      int** ppint = 0;
                      ppint += &i;
                      pint = *ppint;

                      If I'm not mistaken pint is now an int pointer to address 42 and no casting as such has taken place.

                      "The secret of happiness is freedom, and the secret of freedom, courage." Thucydides (B.C. 460-400)

                      S Offline
                      S Offline
                      Stefan_Lang
                      wrote on last edited by
                      #10

                      Matthew Faithfull wrote:

                      ppint += &i;

                      Doesn't work - you only can add integral types (size_t and anything that implicitely converts to size_t) to a pointer. Also, as Harold Aptroot pointed out in response to my variant, even if it would work as intended, pint would point to 42*sizeof(int), not 42.

                      M 1 Reply Last reply
                      0
                      • S Stefan_Lang

                        Matthew Faithfull wrote:

                        ppint += &i;

                        Doesn't work - you only can add integral types (size_t and anything that implicitely converts to size_t) to a pointer. Also, as Harold Aptroot pointed out in response to my variant, even if it would work as intended, pint would point to 42*sizeof(int), not 42.

                        M Offline
                        M Offline
                        Matthew Faithfull
                        wrote on last edited by
                        #11

                        I haven't tried it as it's, as you point out, not of practical use but &i is certainly integral. Another step may be needed to get around restrictions on adding pointers to pointers but the principle is the same. The multiplication by sizeof(int) is not an really issue as this can be overcome without any casting. The addition was a syntactic nicety to explain what I was doing anyway and is not strictly necessary. How about:-

                        int i = 42;
                        int** ppint = &i;
                        int* pint = *ppint;

                        which is shorter and doesn't do pointer arithmetic.

                        "The secret of happiness is freedom, and the secret of freedom, courage." Thucydides (B.C. 460-400)

                        M 1 Reply Last reply
                        0
                        • M MicroVirus

                          Hey coders, I came up with a little puzzle/challenge for C++, so for those interested, my challenge to you is this: Using any C++ constructs, other than any of the casting constructs*, reimplement the following code:

                          int i = someIntValue();
                          int *pint = reinterpret_cast(i)

                          Or in words, find a way to reinterpret_cast an integer into a pointer without casting (implicitly, or explicitly!). You may assume that sizeof(int)==sizeof(int*). I hope to be surprised by answers I hadn't thought of :) * with casting constructs, I mean any form of implicit casts (e.g. int to long int), C-style casts (e.g. (int*)i) and C++-style casts (e.g. reinterpet_cast(i)); and also any functions/macro's/API calls (such as STL implementations) which rely internally on casts. Best Regards, Richard

                          S Offline
                          S Offline
                          Stefan_Lang
                          wrote on last edited by
                          #12

                          The following code compiles and it does return the correct values:

                          int* f1(int i) { return 0; }
                          int* f2(int* pi) { return pi; }
                          union UPointers {
                          int*(*ag1[2])(int i);
                          struct SPointers {
                          int*(*g1)(int i);
                          int*(*g2)(int* pi);
                          } my_spointers;
                          } my_pointers;
                          int* foo(int i) {
                          int* (*h1)(int i);
                          my_pointers.my_spointers.g1 = &f1;
                          my_pointers.my_spointers.g2 = &f2;
                          h1 = my_pointers.ag1[1];
                          return h1(i);
                          }
                          int _tmain(int argc, _TCHAR* argv[])
                          {
                          for (int i = 12; i < 15; ++i) {
                          int* pi = foo(i);
                          std::cout << i << ' ' << pi << std::endl;
                          }
                          return 0;
                          }

                          The output is:

                          12 0000000C
                          13 0000000D
                          14 0000000E

                          The idea is to abuse a function pointer that is supposed to pass an int argument by assigning it to a function that expects an int*. I'm almost sure there is no implicit conversion involved, but I'm not too familiar with function pointers to be sure. The 'conversion' happens when the function call writes the int argument to the stack, but the function that is called interprets it as a int*.

                          M 1 Reply Last reply
                          0
                          • M Matthew Faithfull

                            I haven't tried it as it's, as you point out, not of practical use but &i is certainly integral. Another step may be needed to get around restrictions on adding pointers to pointers but the principle is the same. The multiplication by sizeof(int) is not an really issue as this can be overcome without any casting. The addition was a syntactic nicety to explain what I was doing anyway and is not strictly necessary. How about:-

                            int i = 42;
                            int** ppint = &i;
                            int* pint = *ppint;

                            which is shorter and doesn't do pointer arithmetic.

                            "The secret of happiness is freedom, and the secret of freedom, courage." Thucydides (B.C. 460-400)

                            M Offline
                            M Offline
                            MicroVirus
                            wrote on last edited by
                            #13

                            Dear Matthew, Thanks for submitting your solution. Unfortunately, ppint is of type int**, whereas &i returns an int*, so this will not work without casting int* to int**.

                            M 1 Reply Last reply
                            0
                            • M MicroVirus

                              Dear Matthew, Thanks for submitting your solution. Unfortunately, ppint is of type int**, whereas &i returns an int*, so this will not work without casting int* to int**.

                              M Offline
                              M Offline
                              Matthew Faithfull
                              wrote on last edited by
                              #14

                              I would like to see the assmebler generated for the cast from int* to int**. My expectation is that it would consist of 0 instructions or at most a nop. If no actual cast takes place and none is specified in the code then I say the challenge is met. Assignment from int* to int** is certainly valid. In reality at the backend of most compilers I suspect int* and int** will be same thing anyway. :)

                              "The secret of happiness is freedom, and the secret of freedom, courage." Thucydides (B.C. 460-400)

                              M 1 Reply Last reply
                              0
                              • S Stefan_Lang

                                The following code compiles and it does return the correct values:

                                int* f1(int i) { return 0; }
                                int* f2(int* pi) { return pi; }
                                union UPointers {
                                int*(*ag1[2])(int i);
                                struct SPointers {
                                int*(*g1)(int i);
                                int*(*g2)(int* pi);
                                } my_spointers;
                                } my_pointers;
                                int* foo(int i) {
                                int* (*h1)(int i);
                                my_pointers.my_spointers.g1 = &f1;
                                my_pointers.my_spointers.g2 = &f2;
                                h1 = my_pointers.ag1[1];
                                return h1(i);
                                }
                                int _tmain(int argc, _TCHAR* argv[])
                                {
                                for (int i = 12; i < 15; ++i) {
                                int* pi = foo(i);
                                std::cout << i << ' ' << pi << std::endl;
                                }
                                return 0;
                                }

                                The output is:

                                12 0000000C
                                13 0000000D
                                14 0000000E

                                The idea is to abuse a function pointer that is supposed to pass an int argument by assigning it to a function that expects an int*. I'm almost sure there is no implicit conversion involved, but I'm not too familiar with function pointers to be sure. The 'conversion' happens when the function call writes the int argument to the stack, but the function that is called interprets it as a int*.

                                M Offline
                                M Offline
                                MicroVirus
                                wrote on last edited by
                                #15

                                Dear Stefan, I do indeed think (if I am not mistaken) that your code gets the job done without performing any casts. I also enjoyed seeing you use a union for the job. The solution I had in mind also employs unions, but does not use function pointers:

                                int* withoutCasts(int i)
                                {
                                union {int j; int* pint;} converter;
                                converter.j = i;
                                return converter.pint;
                                }

                                Thanks to everyone who spent time thinking on this, and if anyone has a different solution (possibly one without unions) then I'd love to hear it.

                                S 1 Reply Last reply
                                0
                                • M Matthew Faithfull

                                  I would like to see the assmebler generated for the cast from int* to int**. My expectation is that it would consist of 0 instructions or at most a nop. If no actual cast takes place and none is specified in the code then I say the challenge is met. Assignment from int* to int** is certainly valid. In reality at the backend of most compilers I suspect int* and int** will be same thing anyway. :)

                                  "The secret of happiness is freedom, and the secret of freedom, courage." Thucydides (B.C. 460-400)

                                  M Offline
                                  M Offline
                                  MicroVirus
                                  wrote on last edited by
                                  #16

                                  It's true that in many implementations of C/C++ a pointer to one type is technically (in terms of generated code and storage needs) the same as a pointer to any other type. But in terms of the language, int* is certainly not an int**. At the very least, the compiler will give you an error on the line int **ppi = &i, saying there is no conversion from int* to int**. But ok, that's the compiler, so maybe it's just being annoying? One nice way, I think, of realising these two (int* and int**) are two very different objects is the following:

                                  int* pi = ...;
                                  int** ppi = ...;
                                  *pi; *ppi; // These two are both valid C++ and we know what this means
                                  **ppi; // This is also valid, but the following:
                                  **pi; // Is not valid, and it is not clear what it's suppose to mean; *pi gives an integer value, so what is the dereference of an integer?

                                  So I'd say that int* and int** can't be the same thing, because the one can do something the other can't ;)

                                  1 Reply Last reply
                                  0
                                  • M MicroVirus

                                    Dear Stefan, I do indeed think (if I am not mistaken) that your code gets the job done without performing any casts. I also enjoyed seeing you use a union for the job. The solution I had in mind also employs unions, but does not use function pointers:

                                    int* withoutCasts(int i)
                                    {
                                    union {int j; int* pint;} converter;
                                    converter.j = i;
                                    return converter.pint;
                                    }

                                    Thanks to everyone who spent time thinking on this, and if anyone has a different solution (possibly one without unions) then I'd love to hear it.

                                    S Offline
                                    S Offline
                                    Stefan_Lang
                                    wrote on last edited by
                                    #17

                                    Originally my idea was to use a struct of function pointers and 'iterate' over them to arrive at a different pointer. However, I found that pointer arithmetic apparently doesn't work on function pointers. :( That is when I thought of union. It was only later that I realized the union construct can solve the task by itself. But since I already posted my solution, there was no point in 'watering it down'. ;) Another thing I thought of is overloading virtual functions with different return types. But it would require at least a downcast of the instance pointer:

                                    class base {
                                    public:
                                    virtual ~base() {}
                                    virtual int* foo(int i) { return &i; }
                                    };
                                    class derived : public base {
                                    public:
                                    virtual ~derived() {}
                                    virtual int foo(int i) { return i; } // overrides base::foo()
                                    };
                                    int* bar(int i) {
                                    base* caster = new derived; // implicit downcast here
                                    int* pi = caster->foo(i); // this is the actual 'reinterpret cast'
                                    delete caster;
                                    return pi:
                                    }

                                    I wonder if I could get this to work if I put part of the code inside a constructor, before the construction of the vtable - but then the behaviour would be undefined :doh:

                                    1 Reply Last reply
                                    0
                                    Reply
                                    • Reply as topic
                                    Log in to reply
                                    • Oldest to Newest
                                    • Newest to Oldest
                                    • Most Votes


                                    • Login

                                    • Don't have an account? Register

                                    • Login or register to search.
                                    • First post
                                      Last post
                                    0
                                    • Categories
                                    • Recent
                                    • Tags
                                    • Popular
                                    • World
                                    • Users
                                    • Groups