这是C#中的GetHashCode32方法的代码:

public static class StringHelper
{
    public static unsafe int GetHashCode32(this string s)
    {
        fixed (char* str = s.ToCharArray())
        {
            char* chPtr = str;
            int num = 0x15051505;
            int num2 = num;
            int* numPtr = (int*)chPtr;
            for (int i = s.Length; i > 0; i -= 4)
            {
                num = ( ( (num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
                if (i <= 2)
                {
                    break;
                }
                num2 = ( ( (num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
                numPtr += 2;
            }
            return (num + (num2 * 0x5d588b65));
        }
    }
}


然后用C语言重写此方法,如下所示:

#include <stdio.h>
#include <string.h>

int main()
{
    char    str[320+1];
    memset(str, 0, sizeof(str));
    int     i;
    scanf("%s", str);

    char *chPtr = str;
    int num = 0x15051505;
    int num2 = num;
    int *numPtr = (int*)chPtr;

    for (i = strlen(str); i > 0; i -= 4) {
        num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
        if (i <= 2)
        {
            break;
        }
        num2 = ( ( (num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
        numPtr += 2;
    }
    printf("hash code: %d\n", num + (num2 * 0x5d588b65));
    return 0;
}


c代码在-m32模式下编译。
但是这两个功能有不同的输出

当输入为“ 354707043566597”时

我的c代码输出为637077169,而在GetHashCode32()中应该为-1744455423。

GetHashCode32是C#的库方法。所以是对的。但是我不知道我的C代码有什么问题。
谢谢!

最佳答案

我可以给你一些原因,为什么它可能会有所不同:

首先,0x15051505 == 0b10101000001010001010100000101,如果您计算的话,它是29位长。假定sizeof(int) <= 4,按C标准左移5会产生不确定的行为。

其次,这一行:

int *numPtr = (int*)chPtr;


可能是在C版本中搞砸了(我不知道C#如何处理指针,所以我不能在那说)。当您执行numPtr += 2;时,将其作为char*而不是int*完全不同(一个将其移动2个字节,另一个将其移动2 * sizeof(int)个字节。因此,实际上是在取消引用内存超出字符串范围(假设sizeof(int) == 4),再次导致未定义的行为。

07-28 04:38