因此,在我的 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
以外的值 – 同样的错误:(
我假设你会做这样的事情
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
来代替