c++ - 我可以使用带符号的整数作为 __builtin_popcount() 的参数吗?

标签 c++ gcc g++ gnu

本站:https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html说它是为无符号整数定义的。在某些情况下,将它用于 signed int 是否会给出错误的结果?

最佳答案

__builtin_popcount 是一个特定于 gcc 的扩展。它的行为就像一个带有声明的函数:

int __builtin_popcount (unsigned int x);

如果您有一个带有该声明的实际函数, 它的声明是可见的,那么您可以将任何数字类型的参数传递给它。由于声明是原型(prototype),您传递的任何参数都将隐式转换为参数类型 unsigned int

从(有符号)intunsigned 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/

相关文章:

c++ - 在 Linux 中使用共享库执行二进制文件

c++如何获取具有结构类型的 vector 的大小

c++ - 使用 boost::log 配置文件变量

c++ - GCC 的 STL 排序问题

c++ - 在 friendlyarm qtopia 错误上编译

c++ - 是否有任何理由不将 assert() 包装在解析为 gcc 中的 __builtin_unreachable() 的宏中?

c++ - 为回调用例传递的成员函数指针

linux - gcc中的大尺寸指针

ubuntu - 编译caffe : libpng and libgfortran not found,共享库时出现ld错误

C++/G++ Maxmind geolite2++ 第三方共享对象 undefined reference