这个表达式计算的是什么

时间:2015-10-27 23:27:36

标签: c++ c algorithm

假设 X Y 是两个正整数, Y 是2的幂。然后这个表达式计算什么?

(X + Y-1)& 〜(Y-1)

我发现这个表达式出现在Memory Pool的某些c / c ++实现中( X 表示以字节为单位的对象大小, Y 表示以字节为单位的对齐,表达式返回块大小(以字节为单位)适合在内存池中使用。)

7 个答案:

答案 0 :(得分:3)

&~(Y-1)其中Y是2的幂,将最后的 n 位归零,其中Y = 2 n Y-1产生 n 1位,反转通过〜给出一个掩码,其末尾有 n 零,并且通过位-level &将掩码为零的位清零。

有效地产生的数字是Y 2的幂的倍数。

最大限度地可以从数字中减去Y-1,因此首先添加(X+Y-1) & ~(Y-1)。这是一个不小于X的数字,是Y的倍数。

答案 1 :(得分:2)

它为您提供了当前地址Y的下一个X对齐地址。

说,您当前的地址X0x10000,而您的路线为0x100,它会为您提供0x10000。但是,如果您当前的地址X0x10001,那么您将获得" next"对齐的地址0x10100

这在您希望新对象始终与内存中的块对齐但不会使任何块未使用的情况下非常有用。所以你想知道下一个可用的块对齐地址是什么。

答案 2 :(得分:2)

让我们一点一点地分解它。

(X+Y-1) & ~(Y-1)

假设根据你的规则X = 11和Y = 16,整数是8位。

(11+16-1) & ~(16-1)

添加和减法

(26) & ~(15)

将其翻译成二进制文件

(0001 1010) & ~(0000 1111)

〜表示不反转或反转零和

(0001 1010) & (1111 0000)

&安培;意味着只取两个都是

的位
0001 0000 

转换回十进制

16

其他例子

X = 78, Y = 32 results in 96
X = 25, Y = 64 results in 64
X = 47, Y = 16 results in 48

所以,在我看来,这样做的目的是找到等于或大于X的Y的最低倍数。这可以用于查找内存块的开始/结束地址,或者它可用于在屏幕上定位项目,或任何其他可能的答案。但没有上下文,甚至可能是完整的代码示例。没有保证。

答案 3 :(得分:2)

为什么不尝试一些输入并观察会发生什么?

#include <iostream>

unsigned compute(unsigned x, unsigned y)
{
    return (x + y - 1) & ~(y - 1);
}

int main()
{
    std::cout << "(x + y - 1) & ~(y - 1)" << std::endl;
    for (unsigned x = 0; x < 9; ++x)
    {
        std::cout << "x=" << x << ", y=2 -> " << compute(x, 2) << std::endl;
    }

    std::cout << "----" << std::endl;

    std::cout << "(x + y - 1) & ~(y - 1)" << std::endl;
    for (unsigned x = 0; x < 9; ++x)
    {
        std::cout << "(x=" << x << ", y=2) -> " << compute(x, 2) << std::endl;
    }

    return 0;
}

Live Example

<强>输出: 第一组使用[0,8]中的xy为常量2。第二组使用[0,8]中的xy为常量4

(x + y - 1) & ~(y - 1)
x=0, y=2 -> 0
x=1, y=2 -> 2
x=2, y=2 -> 2
x=3, y=2 -> 4
x=4, y=2 -> 4
x=5, y=2 -> 6
x=6, y=2 -> 6
x=7, y=2 -> 8
x=8, y=2 -> 8
----
(x + y - 1) & ~(y - 1)
(x=0, y=2) -> 0
(x=1, y=2) -> 2
(x=2, y=2) -> 2
(x=3, y=2) -> 4
(x=4, y=2) -> 4
(x=5, y=2) -> 6
(x=6, y=2) -> 6
(x=7, y=2) -> 8
(x=8, y=2) -> 8

很容易看到输出(即->的结果右侧)始终是y的倍数,使得输出大于或等于x

答案 4 :(得分:2)

首先我假设X和Y是无符号整数。

让我们来看看正确的部分:

  • 如果Y是2的幂,则它以二进制形式表示为1比特,所有其他数据表示为0.示例8将是二进制00..01000。
  • 如果减去1,则最高位将为0,其右侧的所有位将变为1.示例8-1 = 7且二进制00..00111
  • 如果你〜否定这个数字,你将确保所有最高位(包括原来的一位将变为1而最喜欢的位为0.例如:~7将是11..11000
  • 现在,如果您使用任何数字进行二进制AND(&amp;),您将在所有低位(在我们的示例中为3位低位)设置为0。因此得到的数字是的倍数

让我们看看左侧:

  • 我们已经分析过Y-1。在我们的例子中,我们有7,即00..00111
  • 如果您将此添加到任何数字,请确保结果大于或等于Y 。示例5:5 + 7 = 12所以00..01100和示例10:10 + 7 = 17所以00..10001
  • 如果您执行AND,则会删除低位。所以在我们的例子中有5,我们来到00..01000 = 8,在我们的例子中有10,我们得到00..10000 16.

结论,它是的最大倍数,大于或等于X

答案 5 :(得分:1)

它似乎提供了一个值的指定对齐,例如内存地址(例如,当你想获得下一个对齐的地址时)。

例如,如果您希望在段落边界处对齐内存地址,则可以编写

( address + 16 - 1 ) & ~( 16 - 1 )

( address + 15 ) & ~15

( address + 15 ) & ~0xf

在这种情况下,16之前的所有位都将归零。

这部分表达

( address + alignment - )

用于舍入。

和表达的这一部分

~( alignment - 1 ) 

用于构建一个掩码为低位的掩码。

答案 6 :(得分:1)

(X + Y-1)&amp; 〜(Y-1)

x = 7 = 0b0111
y = 4 = 0b0100

x+y-1 = 0b1010
y-1 = 3 = 0b0011
~(y-1) = 0b1100

(x+y-1) & ~(y-1) = 0b1000 = 8

-

x = 12 = 0b1100
y = 2 = 0b0010
x+y-1 = 13 = 0b1101

y-1 = 1 = 0b0001
~(y-1) = 0b1110

(x+y-1) & ~(y-1) = 0b1100 = 12

(x + y-1)&amp; 〜(y-1)是y的最大倍数,大于或等于x