(uint64_t)-1是否保证产生0xffffffffffffffff?

时间:2013-08-18 21:08:14

标签: c++ c standards c11

我知道,C标准很好地定义(unsigned)-1必须产生2 ^ n-1,i。即一个无符号整数,其所有位都已设置。 (uint64_t)-1ll也是如此。但是,我在C11标准中找不到指定如何解释(uint64_t)-1的内容。

所以,问题是:C标准中是否有任何保证,以下哪项适用?

(uint64_t)-1 == (uint64_t)(unsigned)-1   //0x00000000ffffffff
(uint64_t)-1 == (uint64_t)(int64_t)-1    //0xffffffffffffffff

4 个答案:

答案 0 :(得分:14)

是。参见C11 6.3.1.3有符号和无符号整数:

  

1当整数类型的值转换为_Bool以外的另一个整数类型时,如果该值可以用新类型表示,则它将保持不变。

     

2否则,如果新类型是无符号的,则通过重复加或减一个可以在新类型中表示的最大值来转换该值,直到该值在新类型的范围内为止。 > 60)

     

3否则,新类型已签名且值无法在其中表示;结果是实现定义的,或者引发实现定义的信号。

     

60)规则描述了数学值的算术,而不是给定表达式的值。

情况2适用,因此-1减少模0x10000000000000000以产生0xffffffffffffffff。

答案 1 :(得分:5)

表达式1-1的类型为int。转换为uint64_t时,加上或减去2 n 直到该值在范围内的原则适用,因此结果总是2 n -1,在这种情况下,n = 64。因此,(uint64_t)-1总是2 64 -1 ..

表达式(int64_t)-1的计算结果为-1,因此相同的推理适用于表达式(uint64_t)(int64_t)-1,它也总是计算为2 64 -1。

另一方面,(unsigned)-1是类型unsigned int的正值,可能是2 16 -1,2 32 -1 ,2 64 -1或其他各种值,具体取决于编译平台。转换为uint64_t时,这些值可能不会产生2 64 -1。

答案 2 :(得分:2)

我猜你是在写(uint64_t)-1而不是-1ULL,因为你不想对unsigned long long的大小做出假设?如果是这样,那很好。但是,有一个替代方案尚未被提及(并且实际上没有回答你的问题),但可以通过侧面提出问题来节省很多担心:

替代

一个好习惯是始终使用UINT64_C(x)代替(uint64_t)x。这是<stdint.h>中定义的宏,可根据需要自动附加UULULL。因此,UINT64_C(-1)会解析为-1U-1UL-1ULL,具体取决于您的目标。这保证始终正常工作。

类型转换的危险

请注意(uint64_t)x实际上甚至无法正常工作。例如,

(uint64_t)2147483648                // RISKY

在某些编译器上生成警告,因为值2147483648(2 ^ 31)太大而无法进入32位整数,并且以下内容甚至无法远程工作:

(uint64_t)1000000000000000000       // RISKY

但是,如果你改用UINT64_C(),那么一切都很好:

UINT64_C(2147483648)                // GOOD

UINT64_C(1000000000000000000)       // GOOD

UINT64_C(-1)                        // GOOD

注意:

  • _C后缀代表“常量”。
  • <stdint.h>中,对于有符号和无符号值,还有8位,16位和32位版本。
  • 对于-1的特殊情况,您也可以只写UINT64_MAX

答案 3 :(得分:-5)

这是一个可以用几行代码回答的问题。

#include <stdio.h>

main()
{
    int          x;
    unsigned int y;

    x = -1;
    printf("\n0x%08x", x);

    y = (unsigned int) -1;
    printf("\n0x%08x", y);

}

在Eclipse / Microsoft C编译器上运行此代码会产生:

0xffffffff
0xffffffff

类似的程序可以显示uint64_t产生的内容。

最后,如果您了解计算机如何使用2的补数来添加数字,那么您将理解-1对于任意位数(8,32,64等)的单词总是对于每个字节的所有ff都是单词/双字等等。