Как работает выравнивание по размеру

Я не могу понять приведенный ниже код относительно предоставленного комментария. Что делает этот код, и что будет эквивалентным кодом для 8-aligned?

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

Вот, ssize имеет unsigned int тип.

6

Решение

Поскольку 4 в двоичном виде равны 100, любое значение, выровненное по 4-байтовым границам (то есть кратное 4), будет иметь последние два бита равными нулю.

3 в двоичном виде — 11, а ~ 3 — побитовое отрицание этих битов, то есть … 1111100. Выполнение побитового И с этим значением сохранит все биты одинаковыми, за исключением двух последних, которые будут очищены (бит & 1 == бит и бит & 0 == 0). Это дает нам следующее меньшее или равное значение, кратное 4.

Чтобы сделать ту же операцию для 8 (1000 в двоичном виде), нам нужно очистить три младших бита. Мы можем сделать это с помощью побитового отрицания двоичного файла 111, то есть ~ 7.

11

Другие решения

Все степени двух (1, 2, 4, 8, 16, 32 …) могут быть выровнены с помощью простых операций a и.

Это дает размер, округленный в меньшую сторону:

size &= ~(alignment - 1);

или если вы хотите округлить:

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

«Alignment-1», если его значение равно степени двух, даст вам «все единицы» до бита только под степенью двойки. ~ инвертирует все биты, поэтому вы получаете единицы для нулей и нули для единиц.

Вы можете проверить, что что-то является степенью двойки:

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

Это работает, потому что, например, 4:

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

или за 16:

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

Если мы используем 5 вместо:

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

Так что не сила двух!

5

Возможно, более понятный комментарий будет

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

Тогда, по крайней мере для меня, мне сразу же задается вопрос: действительно ли оно должно быть округлено, когда это размер? Не будет ли более подходящим округление:

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

Как уже говорилось в других ответах, чтобы выровнять их по 8, нужно обнулить 3 бита, поэтому используйте 7 вместо 3, Итак, мы можем превратить это в функцию:

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

~3 это битовый паттерн ...111100, Когда вы выполняете побитовое И с этим шаблоном, он очищает два нижних бита, то есть округляет до ближайшего кратного 4.

~7 делает то же самое для 8-ми.

2

Код обеспечивает два нижних бита ssize очищаются, гарантируя, что ssize кратен 4. Эквивалентный код для 8-выровнен будет

attr->options.ssize &= ~7;
1
number = number & ~3

число округляется до ближайший кратный 4 то есть меньший чем number
Пример:

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

так же if number is 4,5,6,or 7,числоis rounded off to 4

Но если это связано с выравнивание памяти, память должна быть направлена ​​вверх, а не вниз.

0
По вопросам рекламы [email protected]