0

関数をデバッグしていますhashKey。問題は、異なるプラットフォーム、windows/win ce、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 です。

理由がわかりませんでした。どんな助けでも大歓迎です。前もって感謝します!

詳しくは:

  1. によって引き起こされた、ループ内のいくつかの反復の後、異なる値が始まりますh>>2。したがって、最初は値は同じです。

  2. ansi 文字の入力にはそのような問題はないようです。

2013 年 5 月 3 日に解決しました (Yojimbo のアドバイスのおかげで)。

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;
}
4

3 に答える 3

1

「char」を符号付きとして扱うコンパイラもあれば、そうでないコンパイラもあるのではないでしょうか? 変更してみる

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) は、コンパイラの気まぐれと機械命令セットに応じて、符号ビットを拡張する場合と拡張しない場合があります。

于 2013-04-28T02:35:11.410 に答える
0

ビットごとのシフト演算子を使用しています。問題のプロセッサでバイト順が同じであると確信していますか? x86 はリトル エンディアンを使用します。ARM はビッグ エンディアンまたはリトル エンディアンです。

また、int と long のサイズは異なる場合があります。C++ の唯一のルールは、char <=short <=int <=long <= long long です。正確なサイズは定義されておらず、変更される可能性があります。64 ビット プロセッサの int と long は、通常 32 よりも大きくなります。

于 2013-04-28T02:36:34.313 に答える
0

int と long のサイズは固定されていると想定していますが、そうではありません。プラットフォームによって大きく異なります。https://en.wikipedia.org/wiki/Long_integer#Long_integer

そのコードを 64 ビット ボックスで実行すると、大きな負の数が得られました。stdint.h をインクルードしてみて、「uint32_t」のような明示的にサイズ指定された型を重要な場所で使用してください。(つまり、配列を反復するループは「int」にすることができますが、ビット操作は固定サイズの型にする必要があります。)

于 2013-04-28T02:36:38.833 に答える