Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我可以使用有符号整数作为uu builtin_popcount()的参数吗?_C++_Gcc_G++_Gnu - Fatal编程技术网

C++ 我可以使用有符号整数作为uu builtin_popcount()的参数吗?

C++ 我可以使用有符号整数作为uu builtin_popcount()的参数吗?,c++,gcc,g++,gnu,C++,Gcc,G++,Gnu,此站点:表示它是为无符号整数定义的。在某些情况下,将其用于带符号int是否会产生错误的结果 是的。您也可以传递有符号整数,假设负数表示为2的补码(这在现代系统中最常见) 如果数字为正数,则等于无符号int。但是,如果传递一个负数,例如-1,它将转换为非常大的类型无符号int,,但它不会改变位模式-因此位的数量signed或unsigned与位模式无关,它必须与位模式相关 希望对您有所帮助。\uu内置的popcount是一个特定于gcc的扩展。它的作用类似于具有以下声明的函数: int __bui

此站点:表示它是为无符号整数定义的。在某些情况下,将其用于带符号int是否会产生错误的结果

是的。您也可以传递有符号整数,假设负数表示为2的补码(这在现代系统中最常见)

如果数字为正数,则等于
无符号int
。但是,如果传递一个负数,例如
-1
,它将转换为非常大的类型
无符号int
,但它不会改变位模式-因此位的数量
signed
unsigned
与位模式无关,它必须与位模式相关


希望对您有所帮助。

\uu内置的popcount
是一个特定于gcc的扩展。它的作用类似于具有以下声明的函数:

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

从(有符号)
int
无符号int
的转换定义良好。如果要转换的值在范围
0
INT_MAX
,值不变。否则,它将被包装为模块
UINT\u MAX+1
。例如,将
-1
转换为
unsigned int
会产生
UINT\u MAX
,如果
unsigned int
为32位宽,则为232-1

所以问题是,gcc是否将
\uuuu内置\uuPopCount
视为具有可见原型的函数?因为它是一种语言扩展,所以不必这样做,而且gcc手册也不完全清楚。它显示了它的原型,但这并不一定意味着原型对代码是可见的

GCC4.8.2的实验表明,它被视为具有可见原型的函数。(不能像对普通函数那样将其地址存储在指针中,但这不应该是问题)。该计划:

#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;
}
这意味着
x
的值将转换为
无符号int
,而不仅仅是重新解释。当我们明确地重新解释它的表示时,我们会得到不同的结果

因此,除非gcc出于某种原因(似乎不太可能)更改其内置函数的实现,否则将有符号的
int
传递给
\uuuBuiltin\uPopCount
应该按预期工作,将
int
值转换为
无符号的int
。并且假设有符号整数采用2的补码表示法(这是一个相当安全的假设),从
int
转换为
unsigned int
不会改变表示法,因此
\u builtin\u popcount
将为您提供在
int
表示法中设置的位的正确计数,包括符号位

当然,如果您不想依赖于此,则始终可以使用强制转换将值显式转换为
unsigned int
。强制转换通常容易出错,通常最好使用隐式转换,但在这种情况下,这可能是一种合理的方法

话虽如此,如果要计算一个值的总体计数,几乎可以肯定的是,从一个无符号值开始更合理。您传递给
\u builtin\u popcount
的有符号
int
值很可能应该首先定义为
无符号int

最后,您编写了
\uuuu内置\uPopCount
是“为无符号整数定义的”。实际上,它只为类型
无符号int
定义,一般不为无符号整数定义。有三种不同的内置功能:

int __builtin_popcount (unsigned int x);
int __builtin_popcountl (unsigned long x);
int __builtin_popcountll (unsigned long long x);

您需要为正在处理的数据类型使用正确的方法。在
无符号long-long
对象上使用
\uuuu内置\uPopCount
可能会忽略该值的上半部分,可能不会收到编译器的警告。

为了补充其他答案,下面是一个自己动手,gcc正在做什么的示例。让我们编写一个简单的测试用例:

int f(int i){
  return __builtin_popcount(i);
}
并使用
gcc-c test.c-fdump tree all
编译它。这将创建多个文件,从
test.c.003t.original
开始:

;; Function f (null)
;; enabled by -tree-original

{
  return __builtin_popcount ((unsigned int) i);
}

因此,您可以看到,当对有符号整数调用
\u builtin\u popcount
时,gcc可能会将其转换为有文档记录的参数类型
unsigned int
。如果它说它只为unsigned定义,signed可能有效,也可能无效。不要依赖它。为什么不在调用它之前直接转换为
unsigned int
(一种完全由语言定义的操作)?你打算传递负数吗?如果是的话,你想要什么答案?我认为这通常是无效的,例如第4.7节([conv.integral])。而且它甚至不能保证“内置”某些东西的行为与带有无符号参数的正常函数相似。@DeviceFan:我添加了“假设负数表示为2的恭维(这在系统上是最常见的)。”这假设编译器为
\u内置\u popcount
提供了一个可视原型。事实证明确实如此,但文档中并没有100%明确说明这一点。
int f(int i){
  return __builtin_popcount(i);
}
;; Function f (null)
;; enabled by -tree-original

{
  return __builtin_popcount ((unsigned int) i);
}