Home Dormitory pointers
Post
Cancel

Dormitory pointers

Let’s say we want to have a function that returns an object with some boolean flags in addition. These flags serve as the object’s characterictics. Then we should have something like this:

1
2
3
4
5
template<typename Ty> class ActionResult {
    bool Invalid = false;
    Ty T;
    // some methods...
};

But this doesn’t fit some high-end projects (such as Clang) because of some memory overhead (due to struct’s alignment). If we do a lot of work with pointers, and the said type Ty is often a pointer type, then we can tailor ActionResult exclusively to pointer types.

In this case we can transfer the boolean flags… Right inside the pointer:

1
2
3
template<typename PtrTy> class ActionResult {
    uintptr_t PtrWithInvalid; // let's assume sizeof(uintptr_t) == sizeof(PtrTy*)
};

How does it work? A pointer type is 8 bytes long on 64bit machines, and is capable to address up to 16mlb terabytes of RAM. Here comes that some bits of these 8 bytes (the significant ones) are not used at all, they’re knowingly equal to zero.

We can transfer the Invalid flag into the 0th bit:

1
2
3
     bool isInvalid() const { return PtrWithInvalid & 0x01; }
     bool isUsable() const { return PtrWithInvalid > 0x01; }
     bool isUnset() const { return PtrWithInvalid == 0; }

and shift the pointer to one bit, making room for the flag:

1
2
3
     PtrTy get() const {
       return reinterpret_cast<PtrTy *>((PtrWithInvalid & ~0x01) >> 1);
     }

Clang utilizes pointers with up to three boolean flags (three bits): class PointerIntPair.

One of the most useful example is the QualType class. It contains the pointer to a type (Type*) and qualificator flags (const, restrict, volatile) along with the pointer. Due to the technic described above, these flags don’t utilize more memory at all!

This post is licensed under CC BY 4.0 by the author.

Immutable classes for API data (a practical advice)

Need for speed!