4

我需要用 Java 翻译这行代码,但我不确定如何处理 ptrdiff_t。不知道它在这里做什么。顺便说一下,mask_block 的类型是 size_t。

size_t lowest_bit = mask_block & (-(ptrdiff_t)mask_block);

谢谢

4

4 回答 4

6

谨防!这有点神奇!

( x & ~(x-1) )返回表达式中的最低设置位。由于整数的补码表示,原始代码的作者决定使用( x & (-x) )实际上是相同的。但是(原作者认为)要让你需要使用有符号类型,并且如前所述,是有符号的,是无符号的。-xptrdiff_tsize_t

由于 Java 没有无符号类型,因此mask_block将毫无问题地工作。intmask_block & (-mask_block)

请注意,由于有符号和无符号类型之间的互操作性,强制转换在 C++ 中也是多余的。

于 2013-01-13T21:47:06.073 回答
4

ptrdiff_t是应该用于两个指针之间的(整数)差异的类型。即,一个指针与另一个指针相减的结果。它是一个有符号整数,并且应该足够大以存储最大可能数组的大小(所以在 Java 中,这只是一个int,我猜)

于 2013-01-13T20:34:15.940 回答
3

ptrdiff_t是类型的名称,例如intor ::std::string。C++ 标准承诺这种类型将是一个足够大的整数类型,以容纳您可以减去的任何两个指针之间的差异。当然,减去指针的想法在 Java 中是一个相当陌生的概念。为了能够做到这一点,ptrdiff_t必须能够容纳负数。

使用的子表达式ptrdiff_t是转换表达式,如 Java 类型转换。然而,与 Java 类型转换不同的是,C++ 类型转换表达式更加危险和丑陋。它们可用于 Java 会拒绝的各种不同类型的转换。有时它们会产生令人惊讶的结果。

在这种情况下,看起来有人需要一个值,它是某种无符号整数(可能是一个unsigned long或什么)才能为负数。他们需要把它变成一个有符号的值。ptrdiff_t通常是平台支持的最大大小整数。因此,如果您要将任意无符号整数类型转换为有符号整数类型ptrdiff_t,那么使用的类型最不可能通过 C++ 相当丑陋的强制转换操作导致某种奇怪的截断或符号更改。

特别是,看起来他们想要的类型是size_t,这是 C++ 标准中的另一种类型。它一个无符号类型(就像我猜测的那样),并且保证是一个整数类型,它大到足以容纳内存中任何可能对象的大小。它的大小通常与ptrdiff_t.

编写代码的人想要这样做的原因是一个有趣的位操作技巧。为了向您展示诀窍,我将向您展示此表达式如何在多种场景中发挥作用。

假设mask_block是 48。假设在这个假设的平台上,size_t是 16 位(非常小,但这只是一个示例)。然后在二进制中,mask_block看起来像这样:

0000 0000 0011 0000

并且-(ptrdiff_t)mask_block是-48,看起来像这样:

1111 1111 1101 0000

那么,48 & -48这是不是:

0000 0000 0001 0000

这是 16。请注意,这是 48 中最低设置位的值。让我们试试 50。50 看起来像这样:

0000 0000 0011 0010

-50 看起来像这样:

1111 1111 1100 1110

所以,50 & -50看起来像这样:

0000 0000 0000 0010

这是 2。再次注意这是 50 中最低设置位的值。

所以这只是一个技巧来找到mask. 变量被调用的事实lowest_bit应该是一个线索。:-)

当然,这个技巧并不是完全可移植的。一些 C 和(现在可能是 C++)运行的平台不使用二进制补码表示,这个技巧在这些平台上不起作用。

在 Java 中,您可以这样做long lowest_bit = mask_block & -mask_block;并获得相同的效果。Java 保证二进制补码整数,甚至没有无符号整数。所以它应该工作得很好。

于 2013-01-18T09:28:37.687 回答
1

x & -x是一种清除所有位的技巧,x不包括其最低位。

对于 的所有非零值x,它是1 << lb,其中lb是最低有效位的位置(从 0 开始计数)。

为什么要投到ptrdiff_t? 没有进一步的知识,很难说。我什至不确定是否需要演员阵容。ptrdiff_t保证是有符号整数类型,并且size_t始终是无符号整数类型。所以,我猜想 C++ 代码的作者想要确保它是有符号的并且具有与指针相同的大小。只需忽略强制转换,将代码移植到 Java 就足够了,因为在 Java 中,所有整数都是有符号的。

生成的代码也将比原始 C/C++ 版本更可移植,后者假定机器使用2 的补码来表示整数,尽管(至少在理论上)C 或 C++ 标准不能保证。但是,在 Java 中,保证 JVM 必须使用 2 的补码。

于 2013-01-13T21:48:43.640 回答