10

In The Art of Multiprocessor Programming, p215, the authors say that in C, you could "steal" a bit from a pointer, and using bit-wise operators extract some flag (a mark) and the pointer from a single word. I don't know how this is done, so an example would help me.

Dervin Thunk
  • 19,515
  • 28
  • 127
  • 217
  • 3
    It might be useful to know that this is generally bad practice unless there really is a legitimate reason to do so. – Mysticial Oct 15 '13 at 19:18
  • 1
    @Mysticial: it's common practice for implementing dynamic languages, though. – Fred Foo Oct 15 '13 at 19:19
  • 2
    @Mysticial: there is, when you need to do atomic ops on a single word. – Dervin Thunk Oct 15 '13 at 19:19
  • 1
    I was thinking more on the lines of saving memory when you have large arrays of pointers (with a flag). But yes, those two also apply. (didn't cross my mind initially) – Mysticial Oct 15 '13 at 19:21

2 Answers2

12
  1. Make sure the pointee objects are aligned in memory so that all your pointers are even numbers. The last bit is then free for storing a single boolean flag. (This cannot be done completely portably. so you need knowledge of the platform.)

  2. Move the pointers around as integers of type uintptr_t. These can easily be manipulated:

    bool get_flag(uintptr_t p)
    {
        return p & 1;
    }
    
    void *get_pointer(uintptr_t p)
    {
        return (void *)(p & (UINTPTR_MAX ^ 1));
    }
    
    uintptr_t set_flag(uintptr_t p, bool value)
    {
        return (p & (UINTPTR_MAX ^ 1)) | value;
    }
    
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • How do achieve the same in java? – arunmoezhi Jan 31 '14 at 22:40
  • 2
    In Java, the same functionality (with the intention of synchronising accesses to a shared object) is available with the `AtomicMarkableReference` class. The Nannies today are different than in the last millennia... – Jonatan Lindén Feb 13 '18 at 07:11
  • is this means... that if the pointer is aligned to 8 bytes... we can steal 2 bits ? I have avl tree and I have 1 uint8_t (2 bits) , 3 pointers + data – Nick Aug 17 '23 at 09:57
10

Imagine a system with a 32-bit pointer size, but only 1GB of memory is available. You need only 30 bits to address the entire memory space, so the upper 2 bits are unused. You can use these upper two bits for your own purposes - for example, to mark pointers by pointer type (stack/global vs. dynamic).

Note that the code that you get as the result is about as non-portable as it gets. You need to be intimately familiar with the CPU on which your code runs - specifically, you need to know if the upper bits get dropped when an address from the pointer is sent to the address bus.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 2
    This was very common on 68000-based systems where the address space was only 24 bits - the top 8 bits of a 32 bit address could safely be used for various flags. The original Mac OS back in the 1980s used this trick for locked, purgeable and resource flags. – Paul R Oct 15 '13 at 20:14