0

我在調試函數hashKey。問題是它會在不同的平臺,Windows/win ce,mac os,android下爲同一輸入生成不同的結果。下面是代碼:不同平臺下的按位移運算符(windows,mac os,android)

unsigned long hashKey(const char *name,size_t len) 
{ 
    unsigned long h=(unsigned long)len; 
    size_t step = (len>>5)+1; 
    for(size_t i=len; i>=step; i-=step) 
     h = h^((h<<5)+(h>>2)+(unsigned long)name[i-1]); 
    return h; 
} 

這裏被測試程序使用:

int main() 
{ 
    char word[] = { 0xE6, 0xBE, 0xB3, 0xE9, 0x96, 0x80, 0xE7, 0x89, 0xB9, 0xE5, 
     0x88, 0xA5, 0xE8, 0xA1, 0x8C, 0xE6, 0x94, 0xBF, 0xE5, 0x8D, 
     0x80, 0x2E, 0x70, 0x6E, 0x67, 0x00}; 
    // for those who are interested in what the value of variable means, it means 
    // "澳門特別行政區.png" 

    unsigned int val = hashKey(word, strlen(word)); 
    printf("hash key for [%s] is [%d].\n", word, (unsigned int)val); 
} 

的長度是25時,輸入值是相同的,但是,返回值是不同的:

在android中,它是648. 在win ce中,它是96,這是期望值。

我找不出原因。任何幫助表示讚賞。提前致謝!

更多信息:後在循環,引起h>>2幾個interations

  1. 不同值開始。所以在開始時,值是相同的。

  2. 看來ansi字符的輸入沒有這樣的問題。

5月3日解決(感謝大鏢客的意見),2013年

unsigned long hashKey(const char *name,size_t len) 
{ 
    unsigned long h=(unsigned long)len; 
    size_t step = (len>>5)+1; 
    for(size_t i=len; i>=step; i-=step) 
    { 
     unsigned long charVal = (unsigned long)name[i-1]; 
     if (charVal >= 0x00000080) 
      charVal = charVal | 0xffffff80; 
     h = h^((h<<5 & 0xffffffe0)+(h>>2 & 0x3fffffff) + charVal); 
    } 
    return h; 
} 

回答

1

也許一些編譯器把「炭」的簽署,和別人不一樣?嘗試改變

h = h^((h<<5)+(h>>2)+(unsigned long)name[i-1]); 

h = h^((h<<5)+(h>>2)+(unsigned long)(name[i-1] & 0xff)); 

而且,按位右移(您H >> 2)可擴展符號位與否,取決於編譯器和機器指令集的率性。

+0

是的,你是對的,h >> 2確實會產生不同的結果。但即使我改爲h/4,結果仍然不同... – Hunter 2013-04-28 03:03:07

+0

有什麼解決辦法呢? – Hunter 2013-04-28 03:31:22

+0

此代碼幾乎可能因本頁提到的任何原因而失敗。選擇更少的機器和編譯器相關的算法會更好。這就是說,看看你使用的編譯器是否支持無符號移位運算符>>>。如果他們這樣做,那麼h >>> 2不應該簽署擴展。如果該操作員不可用,那麼您可能不得不依賴位掩碼和位操作符&。例如,如果x是一個32位整數,那麼(x&0x7fffffff)是x的值,高位清零。 (x&0x3fffffff)清除兩個最高位。 – Yojimbo 2013-04-29 11:22:26

0

您正在使用按位移運算符。你確定字節排序在相關處理器上是一樣的嗎? x86使用小端,ARM可以是大端或小端。

此外,int和long的大小可以不同。 C++中唯一的規則是char < = short < = int < = long < = long long。確切的大小沒有定義,可以改變。一個64位的處理器將有更大的整數和長整數,通常比32更長。

+0

有趣的是,不同的值在h >> 2引起的循環中的幾個交織之後開始。所以在開始時,值是相同的。更重要的是,似乎ansi字符的輸入沒有這樣的問題。 – Hunter 2013-04-28 02:52:29

0

您假設整數和長整數的大小是固定的,但它們不是:它們在平臺上變化很大。 https://en.wikipedia.org/wiki/Long_integer#Long_integer

當我在64位盒子上運行該代碼時,我得到了一個很大的負數。嘗試包括stdint.h,並在任何重要的地方使用顯式大小的類型,如「uint32_t」。 (即遍歷數組的循環可以是「int」,但是位操作應該是固定大小的類型)。

+0

我很抱歉地發現,我使用的IDE - vs 2005 - 不支持uint32_t ...這不夠新。 – Hunter 2013-04-28 02:50:26