C ++ unsigned long在4294967295之后不会回滚

时间:2015-06-07 17:43:26

标签: c++ visual-c++ integer g++ long-integer

我正在使用一些c ++代码,并发现如果我用4294967295(其最大允许值)开始一个无符号长整数并添加让我们说6我必须得到5,它确实如此!但是以下添加操作,而mod 255没有给出正确的答案。为什么会这样,以及如何避免?

Plataforms经过测试:
Windows 7,Visual Studio c ++:工作正常;
CentOS版本6.6(最终版),g ++:给出错误的答案;
请参阅代码下方的注释:

#include <stdio.h>
int main(int argc, char *argv[])  {
   unsigned long s1=4294967295;
   unsigned long vp=245;
   unsigned long a;
   unsigned long b;
   unsigned long result;

   /* s1 is 4294967295 + 6 wich is 5  */
   s1+=6;
   a=s1;
   b=255*vp*s1;
   result = (a + b) % 255;
   printf("s1=%u , a=%u , b=%u , (a+b)=%u , (a+b)%255= %u\n", s1, a, b, a + b, result);

   /* s1 is a static value 5 */
   s1=5;

   a=s1;
   b=255*vp*s1;
   result = (a + b) % 255;
   printf("s1=%u , a=%u , b=%u , (a+b)=%u , (a+b)%255= %u\n", s1, a, b, a + b, result);
   return 0;
}

注意: 如果我使用Visual Studio编译代码,我会得到正确的答案。

s1=5 , a=5 , b=312375 , (a+b)=312380 , (a+b)%255= 5
s1=5 , a=5 , b=312375 , (a+b)=312380 , (a+b)%255= 5

但是,如果我使用gcc版本4.4.7 20120313(Red Hat 4.4.7-11)(GCC)编译,我得到:

s1=5 , a=5 , b=312375 , (a+b)=312380 , (a+b)%255= 6
s1=5 , a=5 , b=312375 , (a+b)=312380 , (a+b)%255= 5

如何在g ++中避免它?

2 个答案:

答案 0 :(得分:6)

  

如果我用4294967295(他的最大允许值)开始一个无符号长整数

如果unsigned long是32位类型,则

4294967295只是unsigned long的最大值。在Windows上就是这种情况,包括32位和64位。在Linux上,unsigned long在32位平台上是32位类型,在64位平台上是64位类型。 C ++标准并没有规定类型的特定大小,它只表示unsigned long必须至少为32位,因此Windows和Linux都是正确的。

如果您需要有保证的32位类型,请使用uint32_t中的<cstdint>(如果有)。它是该语言的最新成员,我不知道您的Visual Studio版本是否还有它;如果没有,请参阅'uint32_t' identifier not found error

另外,请注意您在打印输出值时使用的代码中存在错误。它碰巧在您尝试过的两个平台上没有崩溃,但它会在GCC中截断结果。要打印unsigned long,您需要使用%lu说明符,而不是%u。要打印百分比字符,您需要将%加倍。

printf("s1=%lu , a=%lu , b=%lu , (a+b)=%lu , (a+b)%%255= %lu\n", s1, a, b, a + b, result);

或者,由于您使用的是C ++,因此请使用自己的打印机制。

#include <iostream>
…
    std::cout << "s1=" << s1
              << ", a=" << a
              << ", b=" << b
              << ", (a+b)=" << (a+b)
              << ", (a+b)%255=" << result;

unsigned long为64位类型的平台上,第一轮s1的值为4294967301. b的值为268328082129975.您将会这样做如果使用正确的打印说明符,请参阅这些值。

答案 1 :(得分:2)

您使用的是64位系统吗?因为long在GCC中通常是64位,而在Visual Studio编译器中它仍然是32位,这将解释为什么它不能与GCC一起工作但与VS一起工作。

要获得某种类型的最大值,请使用`std::numeric_limits来获取它,例如

unsigned long s1 = std::numeric_limits<unsigned long>::max();