How to allocate a 32-byte aligned memory in C

11,023

First, the question you referred to is 16-byte alignment, not 16-bit alignment.

Regarding your actual question, you just want to mask off 5 bits instead of 4 to make the result 32-byte aligned. So it would be ~0x1F.

To clarify a bit:

To align a pointer to a 32 byte boundary, you want the last 5 bits of the address to be 0. (Since 100000 is 32 in binary, any multiple of 32 will end in 00000.)

0x1F is 11111 in binary. Since it's a pointer, it's actually some number of 0's followed by 11111 - for example, with 64-bit pointers, it would be 59 0's and 5 1's. The ~ means that these values are inverted - so ~0x1F is 59 1's followed by 5 0's.

When you take ptr & ~0x1F, the bitwise & causes all bits that are &'ed with 1 to stay the same, and all bits that are &'ed with 0 to be set to 0. So you end up with the original value of ptr, except that the last 5 bits have been set to 0. What this means is that we've subtracted some number between 0 and 31 in order to make ptr a multiple of 32, which was the goal.

Share:
11,023
Deepanjan Mazumdar
Author by

Deepanjan Mazumdar

Updated on June 04, 2022

Comments

  • Deepanjan Mazumdar
    Deepanjan Mazumdar almost 2 years

    Came across this question in one of the interview samples. A 16-byte aligned allocation has already been answered in How to allocate aligned memory only using the standard library?

    But, I have a specific question in the same regarding the mask used to zero down the last 4 bits. This mask "~0F" has been used such that the resulting address is divisible by 16. What should be done to achieve the same for 32-byte alignment/divisibility?

    • Jim Balter
      Jim Balter over 11 years
      Did you read the detailed answer at the link? There is more than enough information there for you to figure out the answer. If you don't get it, you should study it until you do, because otherwise no answer given here will improve your skills.
    • Jim Balter
      Jim Balter over 11 years
      In fact, there's a generalized implementation there, void test_mask(size_t align) that works for arbitrary power-of-2 alignments, including 32.
    • Jim Balter
      Jim Balter over 11 years
      BTW, you mean 16-byte and 32-byte, not 16-bit and 32-bit.
    • Deepanjan Mazumdar
      Deepanjan Mazumdar over 11 years
      thank you for the correction, will edit the heading
  • Jim Balter
    Jim Balter over 11 years
    It's ~0xF and ~0x1F . And this doesn't answer the question ... look at the link and you will see that more needs to be done than just change the mask.
  • Deepanjan Mazumdar
    Deepanjan Mazumdar over 11 years
    @JimBalter.. i understand that more needs to be done to get the 32-byte aligned address, I only had a doubt regarding the mask.
  • Deepanjan Mazumdar
    Deepanjan Mazumdar over 11 years
    @happydave, thank you for the answer regarding the mask, but I still am not sure how those 5 bits ensure divisibility with 32. I am new to bit semantics, so spare me the ignorance :)
  • Jim Balter
    Jim Balter over 11 years
    @DeepanjanMazumdar If you replaced the last 5 digits of a decimal number with zeroes, the result would be a multiple of 100000, right? Masking with ~0x1F clears the low order 5 bits, so the result is a multiple of 32 = 2**5 = 100000(binary). edit: I see happydave included an explanation in his latest edit ... +1.
  • Deepanjan Mazumdar
    Deepanjan Mazumdar over 11 years
    happydave and jim.. thank you for the explanation.. that clearing amounts to subtraction was skipping my mind.