2015-06-07 62 views
0

我正在玩一些c + +代碼,並發現,如果我開始一個無符號long與4294967295(其最大允許值),並添加讓我們說6我必須得到5,它的確!但是下面的加法操作,以及mod 255並沒有給出正確的答案。爲什麼會發生這種情況,以及如何避免這種情況?C++無符號長不包裹4294967295

Plataforms Tested:
Windows 7,Visual Studio C++:Works Fine;
CentOS release 6.6(Final),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(紅帽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

_「如果我以4294967295(他的最大允許值)開始一個無符號長整型」_你在哪裏讀過這個? –

回答

6

如果我開始一個無符號長與4294967295(他的最大允許值)

4294967295爲unsigned long如果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' 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.如果你使用了正確的打印符你會看到這些值。

+0

uint32可以被發現#include 有uint32_t,這不是一個新的補充。所以優於 user4983898

+0

@ user4983898從C99開始就已經在C語言中,但Windows在實現C99方面已經非常落後。它最近纔剛剛在C++中正式發佈。 – Gilles

2

您是否在64位系統上?因爲然後long通常是GCC中的64位,而在Visual Studio編譯器中它仍然是32位,這將解釋爲什麼它不能與GCC協同工作,但可以與VS協同工作。

要獲得某種類型的最大值,請使用`std::numeric_limits來獲取它。

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

事實上,它打印5和6而不是一個大數字,可能是因爲它們在'printf()'中使用'%u'而不是'%lu'。 – rodrigo

+0

Ops !.我懂了。我將類型更改爲32位無符號整數。現在工作正常。一些編譯器指令todo,謝謝。 – user4983898