0

我在使用这个模数时遇到了很大的困难。C 版本输出我想要的但不是正确的值。我的 C# 输出我不想要的,但输出正确的值。如何获取 C# 版本以输出 C 版本?

C

typedef unsigned long long u64;
typedef unsigned char u8;
static u64 pfd_calculate_hash_table_entry_index(const char *file_name) {
    u64 hash, len, i;

    if (!file_name)
        return -1;

    len = strlen(file_name);
    hash = 0;

    for (i = 0; i < len; ++i)
        hash = (hash << 5) - hash + (u8)file_name[i];
    printf( "%X ", hash);
    printf( "mod ");
    printf( "%X ", 0x39);
    printf( "= %X\n", hash % 0x39 );
    return hash % 0x39;
}

C#

public ulong pfd_calculate_hash_table_entry_index(char[] file_name)
{
    uint hash, len, i;
    hash = 0;
    len = (uint)Array.IndexOf(file_name, '\0');
    for (i = 0; i < len; ++i)
        hash = (hash << 5) - hash + (byte)file_name[i];
    MessageBox.Show(hash.ToString("X") + " mod 0x39 = " + (hash % 0x39).ToString("X"));
    return ((ulong)hash % 0x39);
}

C#

#1: char[] file_name = "PARAM.SFO";
#2: char[] file_name = "RAGE.SAV"

C

#1: char* file_name = "RAGE.SAV";
#2: char* file_name = "PARAM.SFO"

C 哈希

#1: 0x319FFDA7
#2: 0x1A8C4B5B

C# 哈希

#2: 0x319FFDA7
#1: 0x1A8C4B5B

C 输出

#1: 0x319FFDA7 % 0x39 = 0x21;
#2: 0x1A8C4B5B % 0x39 = 0x8;

C# 输出

#1: 0x319FFDA7 % 0x39 = 0xA;
#2: 0x1A8C4B5B % 0x39 = 0xE;

图片...

C

http://puu.sh/3dT5L/52ababeccf.png

C#

http://puu.sh/3dT6P/62b911c102.png

4

1 回答 1

2

好的。正如我所想,这是u64C 和uintC# 之间不匹配的问题,然后被 C 版本中的错误诊断代码混淆。

这很容易在一个简短但完整的 C# 程序中演示:

using System;

public class Test
{
    static void Main()
    {
        ShowHash("PARAM.SFO");
        ShowHash("RAGE.SAV");
    }

    static void ShowHash(string name)
    {
        uint hash = 0;
        foreach (char c in name)
        {
            hash = (hash << 5) - hash + (byte) c;
        }
        Console.WriteLine("0x{0:X} mod 0x39 = {1:X}", hash, hash % 0x39);
    }
}

输出:

0x1A8C4B5B mod 0x39 = E
0x319FFDA7 mod 0x39 = A

改变hashfromuint的类型,ulong我们得到:

0x3FC01A8C4B5B mod 0x39 = 8
0x21B319FFDA7 mod 0x39 = 21

因此,要获得正确的模数,您不需要值 0x1A8C4B5B - 您需要 0x3FC01A8C4B5B。如果您编写了一个简短但完整的 C 程序,它实际上从 0x1A8C4B5B 开始,您会看到它给出与 C# 代码相同的结果。

另外一点,这段代码几乎假设 ASCII 文件名......这肯定对你有效吗?

于 2013-06-12T07:45:06.340 回答