本站:https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html说它是为无符号整数定义的。在某些情况下,将它用于 signed int 是否会给出错误的结果?
最佳答案
__builtin_popcount
是一个特定于 gcc 的扩展。它的行为就像一个带有声明的函数:
int __builtin_popcount (unsigned int x);
如果您有一个带有该声明的实际函数,和 它的声明是可见的,那么您可以将任何数字类型的参数传递给它。由于声明是原型(prototype),您传递的任何参数都将隐式转换为参数类型 unsigned int
。
从(有符号)int
到unsigned int
的转换定义明确。如果转换的值在 0
.. INT_MAX
范围内,则值不变。否则,它是包装模块 UINT_MAX+1
。例如,将 -1
转换为 unsigned int
会产生 UINT_MAX
,如果 则为 232-1 unsigned int
是 32 位宽。
那么问题来了,gcc 是否将__builtin_popcount
视为一个具有可见原型(prototype)的函数?因为它是一种语言扩展,所以它必须,并且 gcc 手册并不完全清楚。它显示了它的原型(prototype),但这并不一定意味着原型(prototype)对您的代码可见。
gcc 4.8.2 的实验表明它被视为具有可见原型(prototype)的函数。 (您不能像普通函数那样将其地址存储在指针中,但这应该不是问题)。这个程序:
#include <stdio.h>
#include <string.h>
int main(void) {
unsigned int n = 21845; // 0x5555, popcount = 8
float x = 21845.0;
unsigned int x_rep;
memcpy(&x_rep, &x, sizeof x_rep);
if (sizeof x != sizeof x_rep) {
puts("WARNING: Sizes do not match");
}
printf("popcount(%u) = %d\n", n, __builtin_popcount(n));
printf("popcount(%g) = %d\n", x, __builtin_popcount(x));
printf("popcount(%u) = %d\n", x_rep, __builtin_popcount(x_rep));
return 0;
}
在我的系统上产生这个输出:
popcount(21845) = 8
popcount(21845) = 8
popcount(1185589760) = 11
这意味着 x
的值被转换为 unsigned int
,而不仅仅是重新解释。当我们明确地重新解释它的表示时,我们会得到不同的结果。
因此,除非 gcc 出于某种原因(这似乎不太可能)更改其内置函数的实现,否则将带符号的 int
传递给 __builtin_popcount
应该会按预期工作,将 int
值到 unsigned int
。并假设有符号整数的 2 的补码表示(这是一个相当安全的假设),从 int
转换为 unsigned int
不会改变表示,所以 __builtin_popcount
将为您提供在 int
表示中设置的正确位数,包括符号位。
当然,如果您不想依赖于此,您始终可以使用强制转换将该值显式转换为 unsigned int
。转换通常容易出错,使用隐式转换通常会更好,但在这种情况下它可能是一种合理的方法。
综上所述,如果您要计算一个值的人口数,几乎可以肯定的是,从无符号值开始更有意义。您传递给 __builtin_popcount
的带符号 int
值应该已定义为 unsigned int
第一名。
最后,您写道 __builtin_popcount
是“为无符号整数定义的”。实际上,它只是为 unsigned int
类型定义的,而不是为一般的无符号整数定义的。共有三种不同的内置函数:
int __builtin_popcount (unsigned int x);
int __builtin_popcountl (unsigned long x);
int __builtin_popcountll (unsigned long long x);
您需要针对所处理的数据类型使用正确的数据。在 unsigned long long
对象上使用 __builtin_popcount
可能会忽略值的上半部分,编译器可能不会发出警告。
关于c++ - 我可以使用带符号的整数作为 __builtin_popcount() 的参数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29879252/