这种尺寸对齐是如何工作的

How is this size alignment working

本文关键字:工作 何工作 对齐      更新时间:2023-10-16

我无法理解以下关于所提供的注释的代码。这段代码有什么作用,8-aligned的等效代码是什么?

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

在这里,ssize属于unsigned int类型。

由于二进制中的 4 是 100,因此任何与 4 字节边界对齐的值(即 4 的倍数)都将最后两位设置为零。

二进制中的 3 是 11,~3 是这些位的按位否定,即......1111100. 使用该值执行按位 AND 将保持每个位相同,除了最后两个将被清除(位 & 1 == 位,位 & 0 == 0)。这给了我们下一个较低或相等的值,它是 4 的倍数。

要对 8(二进制为 1000)执行相同的操作,我们需要清除最低的三位。我们可以通过二进制 111 的按位否定来做到这一点,即 ~7。

2 的所有幂(1, 2, 4, 8, 16, 32...) 都可以通过简单的 a 和操作来对齐。

这给出了向下舍入的大小:

size &= ~(alignment - 1); 

或者,如果您想四舍五入:

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

"alignment-1",只要它是一个 2 的幂的值,就会给你"所有 1",直到 2 的幂。 ~反转所有位,因此您可以得到 1 表示 0,0 表示 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

所以不是两个的幂!

也许更易于理解的评论是

/* 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;
}

~3是位模式...111100。当您使用该模式执行按位 AND 时,它会清除底部的两位,即向下舍入到最接近的 4 的倍数。

~7对 8 对齐执行相同的操作。

该代码确保清除ssize的底部两位,保证ssize是 4 的倍数。 8 对齐的等效代码为

attr->options.ssize &= ~7;
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

但如果这与内存对齐有关,则内存必须向上对齐,而不是向下对齐。