我正在使用一些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 ++中避免它?
答案 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();