manav m-n
manav m-n

Reputation: 11394

How is this size alignment working

I am not able to understand the below code with respect to the comment provided. What does this code does, and what would be the equivalent code for 8-aligned?

/* segment size must be 4-aligned */
attr->options.ssize &= ~3;

Here, ssize is of unsigned int type.

Upvotes: 8

Views: 6923

Answers (6)

hyde
hyde

Reputation: 62797

Perhaps more understandable comment would be

/* make segment size 4-aligned
   by zeroing two least significant bits, 
   effectively rounding down */

Then at least for me, immediate question pops to my mind: should it really be rounded down, when it is size? Wouldn't rounding up be more appropriate:

attr->options.ssize = (attr->options.ssize + 3) & ~3;

As already said in other answers, to make it 8-aligned, 3 bits need to be zeroed, so use 7 instead of 3. So, we might make it into a function:

unsigned size_align(unsigned size, unsigned bit_count_to_zero) 
{
  unsigned bits = (1 << bit_count_to_zero) - 1;
  return (size + bits) & ~bits;
}

Upvotes: 5

sr01853
sr01853

Reputation: 6121

number = number & ~3

The number is rounded off to the nearest multiple of 4 that is lesser than number Ex:

      if number is 0,1,2 or 3, the `number` is rounded off to 0

similarly if number is 4,5,6,or 7,numberis rounded off to 4

But if this is related to memory alignment, the memory must be aligned upwards and not downwards.

Upvotes: 0

Mats Petersson
Mats Petersson

Reputation: 129374

All powers of two (1, 2, 4, 8, 16, 32...) can be aligned by simple a and operation.

This gives the size rounded down:

size &= ~(alignment - 1); 

or if you want to round up:

size = (size + alignment-1) & ~(alignment-1);

The "alignment-1", as long as it's a value that is a power of two, will give you "all ones" up to the bit just under the power of two. ~ inverts all the bits, so you get ones for zeros and zeros for ones.

You can check that something is a power of two by:

bool power_of_two = !(alignment & (alignment-1))

This works because, for example 4:

4    = 00000100
4-1  = 00000011
&      --------
0    = 00000000

or for 16:

16   = 00010000
16-1 = 00001111
&      --------
0    = 00000000

If we use 5 instead:

5    = 00000101
4-1  = 00000100
&      --------
4    = 00000100

So not a power of two!

Upvotes: 13

R. Martinho Fernandes
R. Martinho Fernandes

Reputation: 234504

Since 4 in binary is 100, any value aligned to 4-byte boundaries (i.e. a multiple of 4) will have the last two bits set to zero.

3 in binary is 11, and ~3 is the bitwise negation of those bits, i.e., ...1111100. Performing a bitwise AND with that value will keep every bit the same, except the last two which will be cleared (bit & 1 == bit, and bit & 0 == 0). This gives us a the next lower or equal value that is a multiple of 4.

To do the same operation for 8 (1000 in binary), we need to clear out the lowest three bits. We can do that with the bitwise negation of the binary 111, i.e., ~7.

Upvotes: 15

simonc
simonc

Reputation: 42175

The code ensures the bottom two bits of ssize are cleared, guaranteeing that ssize is a multiple of 4. Equivalent code for 8-aligned would be

attr->options.ssize &= ~7;

Upvotes: 1

Graham Borland
Graham Borland

Reputation: 60681

~3 is the bit pattern ...111100. When you do a bitwise AND with that pattern, it clears the bottom two bits, i.e. rounds down to the nearest multiple of 4.

~7 does the same thing for 8-aligned.

Upvotes: 3

Related Questions