简体   繁体   中英

How to cast long unsigned to unsigned char*?

I am trying to hash an unsigned long value, but the hash function takes an unsigned char * , as seen in the implementation below:

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

Is there a way I can achieve my goal, perhaps with a cast between the two?

unsigned long x;

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

Make sure you use all 4 bytes through the p , or whatever is the length of unsigned long on your system.

Technically you can achieve it with:

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

Mind the usual pitfalls, however:

  • The hash function in question was originally meant for strings (hence the prototype), so make sure it fits your needs (# of collisions, avalanching, etc.)
  • If at some point you want to hash very large objects for which sizeof(object) > (int) sizeof(object) (if applicable on your architecture(s)), note you might get out of bounds accesses (undefined behaviour) or only part of your object hashed.

As other said, you can easily read an int or any other object as a char array :

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

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

But note that 0xdead stored in a short or a long won't have the same hash .

Also note that your hash function could be better unrolled using a 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;
}

This shows a cast working. Note that in this case the "ABC" string will be null terminated but this may require more care in real world cases

#include <stdio.h>

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

Since you've posted your code now, you'd want to use something similar to this:

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

你应该使用ultoa_s转换它

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM