__builtin_clz 使用非 0 的有效输入返回错误答案

问题描述 投票:0回答:1

因此,在我的 M1 MacBook 上,我正在编写一个库(使用 Apple Clang),为此我需要计算某些数字的前导(和尾随,但这似乎工作得很好)零的数量。

我显然选择了简单的路线,只使用了

__builtin_clz
,这样我就不必对项目的这一部分进行任何位操作。现在,我发现了一个错误,并将其追溯到所述函数。一些测试表明,对于
__builtin_clz
uint8_t
等于
1
的情况,它返回
31
。对于
uint16_t
也等于
1
,对于
uint32_t
uint64_t
也是如此。

这让我觉得很奇怪,因为

sizeof(uintN_t)
总是返回预期值(分别为
1
2
4
8
)。

我正在使用

-O3
-march=native
进行编译,其中 可能 会导致一些问题,但由于我仅在自己的计算机上运行该程序,因此第二个应该不会有任何问题,并且优化级别应该只可能在调用UB时导致奇怪的错误,我没有这样做,因为我没有将0放入函数中,只将有效参数放入其中。

关于这个问题我可以查阅任何文档吗?有人对问题可能出在哪里有什么建议吗?我知道我可以自己做一些位屏蔽,但这会破坏该函数的整个目的,并且无法解决此错误。

提前致谢!

附注当然,我测试了

1
以外的值 – 同样的错误:(

c++ debugging clang undefined-behavior built-in
1个回答
0
投票

我假设你会做这样的事情

uint8_t n = 1;
std::cout << __builtin_clz(n) << '\n';

因此正确的结果将是 31,因为

__builtin_clz
接收到
unsigned int
作为参数。在传递给函数之前,Clang 会将您的输入转换为
uint32_t
。根本就没有什么bug啊如果编译器为此类基本操作产生错误的结果,我会感到惊讶。有
__builtin_clzl
__builtin_clzll
分别接收
unsigned long
unsigned long long
。还有
__builtin_clzg
但没有专门针对
uint8_t

的版本

但不要使用特定于编译器的内置函数。在 C++ 中,您应该使用

std::countl_zero
std::countr_zero
来代替

© www.soinside.com 2019 - 2024. All rights reserved.