When is an integer<->pointer cast actually correct?

后端 未结 15 2614
北荒
北荒 2020-12-13 07:48

The common folklore says that:

  • The type system exists for a reason. Integers and pointers are distinct types, casting between them is a malpractice in the m

相关标签:
15条回答
  • 2020-12-13 08:28

    Storing a doubly linked list using half the space

    A XOR Linked List combines the next and prev pointers into a single value of the same size. It does this by xor-ing the two pointers together, which requires treating them like integers.

    0 讨论(0)
  • 2020-12-13 08:28

    under x64, on can use the upper bits of pointers for tagging (as only 47 bits are used for the actual pointer). this is great for things like run time code generation (LuaJIT uses this technique, which is an ancient technique, according to the comments), to do this tagging and tag checking you either need a cast or a union, which basically amount to the same thing.

    casting of pointers to integers can also be very helpful in memory management systems that make use of binning, ie: one would be able to easily find the bin/page for an address via some math, an example from a lockless allocator I wrote a while back:

    inline Page* GetPage(void* pMemory)
    {
        return &pPages[((UINT_PTR)pMemory - (UINT_PTR)pReserve) >> nPageShift];
    }
    
    0 讨论(0)
  • 2020-12-13 08:31

    You may need to access memory at a fixed known address, then your address is an integer and you need to assign it to a pointer. This is somewhat common in embedded systems. Conversely, you may need to print a memory address and thus need to cast it to integer.

    Oh, and don't forget you need to assign and compare pointers to NULL, which is usually a pointer cast of 0L

    0 讨论(0)
  • 2020-12-13 08:32

    I sometimes cast pointers to integers when they somehow need to be part of a hashsum. Also I cast them to integers to do some bitfiddling with them on certain implemetnations where it is guaranteed that pointers always have one or two spare bits left, where I can encode AVL or RB Tree information in the left/right pointers instead of having an additional member. But this is all so implementation specific that I recommend to never think about it as any kind of common solution. Also I heard that sometimes hazard pointers can be implemented with such a thing.

    In some situations I need a unique ID per object that I pass along to e.g. servers as my request id. Depending on the context when I need to save some memory, and it is worth it, I use the address of my object as such an id, and usually have to cast it to an integer.

    When working with embedded systems (such as in canon cameras, see chdk) there are often magic addesses, so a (void*)0xFFBC5235 or similar is often found there too

    edit:

    Just stumbled (in my mind) over pthread_self() which returns a pthread_t which is usually a typedef to an unsigned integer. Internally though it is a pointer to some thread struct, representing the thread in question. In general it might used elsewhere for an opaque handle.

    0 讨论(0)
  • 2020-12-13 08:34

    Pointer values can also be a useful source of entropy for seeding a random number generator:

    int* p = new int();
    seed(intptr_t(p) ^ *p);
    delete p;
    

    The boost UUID library uses this trick, and some others.

    0 讨论(0)
  • 2020-12-13 08:35

    It could be useful when checking the alignment of types in general so that misaligned memory gets caught with an assert rather than just SIGBUS/SIGSEGV.

    E.g.:

    #include <xmmintrin.h>
    #include <assert.h>
    #include <stdint.h>
    
    int main() {
      void *ptr = malloc(sizeof(__m128));
      assert(!((intptr_t)ptr) % __alignof__(__m128));
      return 0;
    }
    

    (In real code I wouldn't just gamble on malloc, but it illustrates the point)

    0 讨论(0)
提交回复
热议问题