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

0 c++ integer g++ visual-c++ long-integer

我正在玩一些c ++代码,发现如果我用4294967295(它的最大允许值)开始一个unsigned long并添加让我们说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;
}
Run Code Online (Sandbox Code Playgroud)

注意:如果我使用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
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用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
Run Code Online (Sandbox Code Playgroud)

如何在g ++中避免它?

Gil*_*il' 6

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

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

如果你想有一个保证的32位类型,使用uint32_t<cstdint>(如果可用).这是该语言的最新成员,我不知道您的Visual Studio版本是否还有它; 如果没有,请参阅'uint32_t'标识符未找到错误.

另外,请注意您用于打印值的代码中存在错误.它碰巧在您尝试过的两个平台上没有崩溃,但它会在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);
Run Code Online (Sandbox Code Playgroud)

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

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

unsigned long64位类型的平台上,s1第一轮的值为4294967301.值为b268328082129975.如果使用正确的打印说明符,您将看到这些值.