无符号Long Long超出范围?

时间:2012-12-10 02:13:54

标签: c++ objective-c c 64-bit long-integer

好的,这是一个奇怪的问题:

  • 我正在使用unsigned long long个变量(我使用了long个变量,效果相同)
  • 需要能够存储64位整数(sizeof返回8,这很好)

但是,当我尝试使用像1<<63这样的值,并执行一些简单的按位操作时,奇怪的是,我似乎得到了负值。为什么?

我的测试代码:

    unsigned long long c = 0;

    c |= 1l << 56; printf("c = %lld\n",c);
    c |= 1l << 63; printf("c = %lld\n",c);

输出

c = 72057594037927936 
c = -9151314442816847872

旁注:

  1. 当然,即使我直接c = 1l<<63,也会发生同样的事情。
  2. 在Mac OS X 10.6上进行的所有测试,并使用Apple的LLVM编译器3.0进行编译

  3. 有什么建议吗?

2 个答案:

答案 0 :(得分:22)

d说明符的%lld部分告诉printf该参数应该被视为有符号整数。请改用u%llu

从手册页:

  

d,我

     
    

int参数转换为 signed 十进制表示法。

  
     

o,u,x,X

     
    

unsigned int参数转换为 unsigned 八进制(o),无符号十进制(u)或无符号十六进制(x和X) )符号。

  

答案 1 :(得分:4)

我认为你实际上在这里做了一些未定义的事情。我认为表达式1l << 63在C中是未定义的,因为编译器将在有符号类型中表示1l,并且移位63位会导致有符号溢出(在C中未定义)。我不是专家,但似乎你想要1ull << 63

如果您在clang中传递-Weverything,您的原始代码实际上会抱怨这一点:

foo.c:7:23: warning: signed shift result (0x8000000000000000) sets the sign bit of the
            shift expression's type ('long') and becomes negative [-Wshift-sign-overflow]
      c |= 1l << 63; printf("c = %lld\n",c);
           ~~ ^  ~~

编辑:是的,那么你需要从另一个答案中获得正确的printf格式。