__builtin_clz 的 Java 等价物是什么?

时间:2021-02-13 13:11:24

标签: java c

我需要一个相当于 __builtin_clz 的 Java。

感觉答案应该是Long.numberOfLeadingZeros,但它们返回的答案完全不同。

我开始怀疑这是否有一个低级的原因——也许是字节序?还是一些未签名的怪癖?

编辑:误报。这纯粹是由打字错误引起的 - 原始代码实际上调用了 __builtin_ctzll 并与 Long.numberOfTrailingZeros

匹配

3 个答案:

答案 0 :(得分:4)

Long.numberOfLeadingZeros 完全正确。

您得到不同答案的事实是因为 C.C 没有定义 int 的含义。因此,__builtin_clz(a) 给出的答案在您运行它的每个框上都不同:它取决于 int 的位宽,并且根据 C 标准,{{1} } 是对你正在编译的系统方便的任何东西。如果是 32 位(这是很常见的位宽),int 会返回 27。如果是 64 位(也很常见),__builtin_clz(16) 会返回 59。

Java 通常不会“做”整个未定义 的事情。在 java 中,与 C 不同,__builtin_clz(16) 是一个有符号的 32 位数字。无论您在什么 VM、版本、平台或操作系统上运行或编译它。类似地,long 是有符号的 64 位。

尽管如此,intLong.numberOfLeadingZeroes 一样有效地将数字视为无符号数:这意味着 __builtin_clz,其中 x 是负数,总是返回 0(或者应该,根据C 规范),而 __builtin_clz(x) 的作用完全相同:对于负数,始终返回 0(无前导零位)。

换句话说,在 64 位系统上,Long.numberOfLeadingZeros 与 java 中的 __builtin_clz(x) 完美匹配。在 32 位系统上,Long.numberOfLeadingZeros(x) 返回的值小于 32(64 位上的 __builtin_clz(x) 为 59,但在 32 位上为 27),而在 Java 中,您必须使用 { {1}} 代替。 __builtin_clz(16) 返回 27。就像 Integer.numberOfLeadingZeros() 一样,如果目标是 Integer.numberOfLeadingZeros(16) 定义为 32 位的系统(如果目标是 32 位处理器)。

答案 1 :(得分:1)

误报:由拼写错误引起 - 我实际上需要 __builtin_ctzll 代替,现在更有意义了。

答案 2 :(得分:-1)

__builtin_clz() 计算非零 int 值中前导零的数量。这个数字取决于 int 类型的表示,因此在 java 中没有直接等价,因为 C 标准整数类型中的位数,例如 intlonglong long是实现定义的,而 Java 规范固定了类型 intlong 的大小和表示。

除了 __builtin_clz(int) 之外,gcc 还定义了 __builtin_clzl(long)__builtin_clzll(long long)。在当前的大多数系统上,C ABI 定义了 32 位的 int 和 64 位的 long long,使得 Integer.numberOfLeadingZeros(int)Long.numberOfLeadingZeros(long) 分别相当于 __builtin_clz 和 {{ 1}}。但是请注意,Java 函数为 C 内置函数没有的零参数定义了行为,因为它们是作为单个 CPU 指令实现的(在某些体系结构上)。

__builtin_clzll__builtin_ctz(int)__builtin_ctzl(long) 计算相应类型的非零参数中尾随零的数量。对于非零值,尾随零的数量仅取决于参数的值,而不取决于其类型大小。对应的java方法是__builtin_ctzll(long long)Integer.numberOfTrailingZeros(int)。这些方法是为所有参数值定义的,对于零参数分别返回 Long.numberOfTrailingZeros(long)32