2013-05-14 81 views
2

我試圖散列一個unsigned long值,但是哈希函數接受一個unsigned char *,如下面的實施看出:如何將無符號長符號轉換爲unsigned char *?

unsigned long djb2(unsigned char *key, int n) 
{ 
    unsigned long hash = 5381; 
    int i = 0; 
    while (i < n-8) { 
     hash = hash * 33 + key[i++]; 
     hash = hash * 33 + key[i++]; 
     hash = hash * 33 + key[i++]; 
     hash = hash * 33 + key[i++]; 
     hash = hash * 33 + key[i++]; 
     hash = hash * 33 + key[i++]; 
     hash = hash * 33 + key[i++]; 
     hash = hash * 33 + key[i++]; 
    } 
    while (i < n) 
     hash = hash * 33 + key[i++]; 
    return hash; 
} 

有沒有一種方法可以讓我實現我的目標,也許與兩者之間的投?

+0

的reinterpret_cast,但它的醜陋。什麼哈希函數需要char *? – Pubby 2013-05-14 07:07:46

+2

@Pubby,'reinterpret_cast'是C++,問題是C. – 2013-05-14 07:14:11

+0

它可能只是我,但我認爲在這個問題中應該有更多的上下文(即更多的代碼)。 – tay10r 2013-05-14 07:14:36

回答

11
unsigned long x; 

unsigned char * p = (unsigned char*)&x; 

確保你使用的所有4個字節通過p,或什麼是unsigned long系統上的長度。

+0

你是什麼意思「使用所有4字節通過p」?對不起,我是新手c – James 2013-05-14 07:15:51

+3

而且,不要忘記endian問題!如果您沒有適當地交換endian,您可能會在不同的機器上爲「相同」數據獲得不同的哈希值。 – tangrs 2013-05-14 07:17:27

+2

p是一個指針。它指向你的無符號long的第一個字節。在這種情況下,一個名爲'x'的變量。我想你有一個函數需要一個usnigned字符指針和一些長度。如果是這種情況,長度應該是sizeof(usnigned long)或sizeof(x)。 – user1764961 2013-05-14 07:18:11

-2

您應該將其轉換爲ultoa_s

+0

他從來不說字符串。問題是關於強制轉換數據類型 – tay10r 2013-05-14 07:17:26

+0

您不能將ulong轉換爲以空字符結尾的字符串並使用指針嗎? – dizzer 2013-05-14 07:21:57

+0

@dizzer:你如何期望'0x10000010'看起來像一個0結尾的字符串? – glglgl 2013-05-14 07:25:06

0

這顯示了演員表演。請注意,在這種情況下,「ABC」字符串將空終止,但既然你已經發布,現在你的代碼,這可能需要在現實世界中的情況下

#include <stdio.h> 

int main() { 
    unsigned long x=0x414243; #0x414243 is ABC 
    unsigned char *s=(unsigned char *)&x; 
    printf("%s", s); 
} 
+0

在你的例子中,它將是'ABC',但只在大端系統上。編輯:實際上,在大端系統上,它只是一個空字符串。 – tangrs 2013-05-14 07:24:19

+0

是的,這是典型的英特爾Linux系統上的「CBA」:) – Vorsprung 2013-05-14 07:24:54

0

更多的照顧,你想使用類似這樣的東西:

#include <stdio.h> 


int main() { 
    unsigned long result, x = 0xdeadbeef; 
    x = convert_endian(x); 

    result = djb2((unsigned char*)&x, sizeof(x)); 
    do_something(result); 
    return 0; 
} 
+0

不,它不是。它可以在任何大小的情況下正常工作 – SomeWittyUsername 2013-05-14 07:47:07

+0

@icepack它仍然以小於8字節的方式循環,但會產生分段錯誤。這樣,它確實預計了一個大小爲%8的緩衝區== 0 – tay10r 2013-05-14 07:50:02

+0

@TaylorFlores仔細觀察,如果大小小於8,它將不會循環。 – SomeWittyUsername 2013-05-14 07:53:55

1

從技術上講,你可以實現它:

unsigned long value = 58281; 
djb2((unsigned char *) &value, sizeof(value)); 

心靈平常的陷阱,但是:

  • 有問題的散列函數最初旨在用於字符串(因此原型),所以一定要確保它符合您的需求
  • (碰撞,雪崩等的#)如果在某些時候你想哈希非常大的對象對於其中的sizeof(object) > (int) sizeof(object)(如果適用於您的體系結構),請注意您可能會超出界限訪問(未定義行爲),或者只有部分對象散列。
+0

我認爲'sizeof x'而不是'sizeof(x)'比'return(x)'而不是'return x'更稀有:) – SomeWittyUsername 2013-05-14 08:20:55

+0

也許是壞習慣。 :-) – 2013-05-14 08:23:54

+0

我其實覺得很爽:) – SomeWittyUsername 2013-05-14 08:26:36

1

至於對方說,你可以很容易地讀取int或其他任何對象作爲char陣列:

unsigned char value = 0xde; 
unsigned short value = 0xdead; 
unsigned long value = 0xdeadbeef; 
double value = 1./3; 

djb2((unsigned char*)&value, sizeof value); 

但需要注意的是存儲在一個short0xdeadlong不會有相同的哈希

另外請注意,您的哈希函數可以使用Duff's device更好地展開:

unsigned long djb2(unsigned char *k, int size) 
{ 
    unsigned long h = 5381; 
    int i = 0; 
    switch(size % 8) { 
     case 0: while(i < size) { 
        h = h*33 + k[i++]; 
     case 7:  h = h*33 + k[i++]; 
     case 6:  h = h*33 + k[i++]; 
     case 5:  h = h*33 + k[i++]; 
     case 4:  h = h*33 + k[i++]; 
     case 3:  h = h*33 + k[i++]; 
     case 2:  h = h*33 + k[i++]; 
     case 1:  h = h*33 + k[i++]; 
       } 
    } 
    return h; 
} 
+0

+1,有趣的展開技巧 – SomeWittyUsername 2013-05-14 09:41:58