1

Alright, I'm hashing an image. And as you all know, hashing an image takes FOREVER. So I'm taking 100 samples of the image, evenly spaced out. Here's the code.

#define NUM_HASH_SAMPLES 100

@implementation UIImage(Powow)

-(NSString *)md5Hash
{
    NSData *data = UIImagePNGRepresentation(self);

    char *bytes = (char*)malloc(NUM_HASH_SAMPLES*sizeof(char));
    for(int i = 0; i < NUM_HASH_SAMPLES; i++)
    {
        int index = i*data.length/NUM_HASH_SAMPLES;

        bytes[i] = (char)(data.bytes[index]); //Operand of type 'const void' where arithmetic or pointer type is required
    }

    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5( bytes, NUM_HASH_SAMPLES, result );
    return [NSString stringWithFormat:
            @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
            result[0], result[1], result[2], result[3],
            result[4], result[5], result[6], result[7],
            result[8], result[9], result[10], result[11],
            result[12], result[13], result[14], result[15]
            ];
}

The error is on the commented line.

What am I doing wrong?

rweichler
  • 103
  • 2
  • 7

2 Answers2

4

data.bytes is a void *, so it makes no sense to dereference it (or even to perform the necessary pointer arithmetic on it).

So, if you meant to take a byte out of the data, then obtain a pointer to const unsigned char and dereference that:

const unsigned char *src = data.bytes;
/* ..then, in your loop.. */
bytes[i] = src[index];

Oh, and do not cast the return value of malloc()!

Community
  • 1
  • 1
  • Thanks! However, I found that doing bytes[i] = &data.bytes[index] was a bit cleaner. And my computer science professor told me it was good practice to cast mallocs. Go figure. – rweichler Aug 28 '13 at 09:53
1

According to the documentation for NSData, data.bytes returns a type of const void *. Basically, you're trying to access a pointer to void which makes no sense since void doesn't have a size.

Cast it to a char pointer and dereference it.

((const char *)data.bytes)[index]

or

*((const char *)data.bytes + index)

Edit: What I'd normally do is assign the pointer to a known data type straight away and use that instead.

I.e.

const char *src = data.bytes;
bytes[i] = src[index];

Edit2: You might also want to leave the const qualifier in as suggested by H2CO3. That way you won't accidentally write to a location you're not supposed to.

tangrs
  • 9,709
  • 1
  • 38
  • 53
  • Even better: `((const char *)data.bytes)[index]`; even slightly better: `((const unsigned char *)data.bytes)[index]` perfect: `const unsigned char *bytes = data.bytes; bytes[index];` –  Aug 27 '13 at 08:51