-1

I would like to save some space by truncating my pointer addresses by 1 byte. My pointers are guaranteed to be 16-byte memory aligned. Thus, I can guarantee that those 4 bottom bits can be truncated.

typedef struct node_t {
   uintptr_t prev : 29;
   uintptr_t next : 29;
} node;

I am struggling to restore those bottom-most bytes. Bit shifting 4 bits to the left in an attempt to restore the zeroes in the bottom-most bits only erases the data from the front-most bytes.

node->next = ((uintptr_t) ptr_addrs >> 4); // successfully stores truncated pointer ex: 0x1024ff010
printf("%p\n", node->next); // prints '0x1024ff01'

How do I convert the bitfield back to its original value (basically appending a zero to this bitfield)?

Peabrain
  • 519
  • 2
  • 12
  • 1
    Have you checked to see if this actually makes any difference to `sizeof(node)`? – Retired Ninja Mar 07 '21 at 05:13
  • yes; on my system if I were to use the full field I get sizeof(node) = 16, while using bitfields has sizeof(node) = 8 – Peabrain Mar 07 '21 at 05:22
  • So you're compiling for 64 bit? – Retired Ninja Mar 07 '21 at 05:23
  • yes; on a Linux 64-bit machine; compiling using gcc – Peabrain Mar 07 '21 at 05:25
  • @RetiredNinja Not even on an 8-bit CPU (the smallest reasonable CPU type to use C at all), definitively not anything larger and not with ´uintptr_t´ unless we have a most exotic architecture. @OP: 4 bits are not a byte in C. That's a nibble and not even addressable. And your `printf` invokes undefined behaviour already. If you'd save anything, your original assumption about alignment would be wrong already. If you are on an arch with 32 bit addresses, 32-29 =3, not 4. – too honest for this site Mar 07 '21 at 05:28
  • 64 - 4 != 29. You may wish to rethink that as well as check if it does make your struct smaller. It shouldn't because of alignment. – Retired Ninja Mar 07 '21 at 05:28
  • As a friendly (honestly!) advice, you might want to re-thing all this after doing some resaearch about bitfields, pointers and ´uintptr_t´ and constraints about conversions in the C language. – too honest for this site Mar 07 '21 at 05:28
  • @RetiredNinja: it's not just alignment, but that#s not even a byte. Btw. we don#t even know the architecture, I just assumed it is some 32 bit CPU, possibly MCU. However, this won't save a bit, but will eventually cause a bunch of problems. Edit: just saw the comment its a 64 bit CPU. OP: what about bits 63..32?? – too honest for this site Mar 07 '21 at 05:30
  • @toohonestforthissite I know, just trying to help them reason it out for themselves. – Retired Ninja Mar 07 '21 at 05:31
  • 1
    @RetiredNinja: I honestly already have a problem where to start what's all wrong about this. That's why I tried to point him at the subjects to research. – too honest for this site Mar 07 '21 at 05:37

1 Answers1

1

First, if pointers were 32 bits, removing 4 bits leaves 28 bits, not 29. So declaring bit-fields of 29 bits appears to be wrong. No platform uses 33 bits for pointers. 29 bits would certainly be enough to store 28 bits, but it is too big to save any space—the total space requirement of your structure would be at least 58 bits, which requires eight eight-bit bytes, since seven bytes could hold only 56 bits.

Second, the fact that using a “full field” for your structure takes 16 bytes indicates that uintptr_t is eight bytes and so the pointers for your platform are eight bytes, 64 bits. Removing four bits from that leaves 60 bits, not 28 or 29.

To answer your question “How do I convert the bitfield back to its original value,” simply shift left by four bits and convert back to the original pointer type.

(Sometimes systems that use 64 bits for pointers do not use all of those bits; the actual address space could be 44 bits or some other number, in which case you can save space by storing only the used bits. However, this sort of pointer compaction is time consuming and saves only a modest amount of space by today’s economics. Unless you are overflowing main memory with structures consisting in great portion of pointers, it is unlikely to be worthwhile. Would the amount of space saved per pointer multiplied by the number of pointers reduce your memory use below the threshold where performance is degraded?)

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312