tags:

views:

205

answers:

3

Hi, I have an array of chars and a pointer to it. I need to add the first 8Bytes (binary value of the 8 Bytes) to the second 8 bytes modulo 2exp(64). How could I do that?

I found a solution. But it is definitely not good to do such things (see the code). Nevertheless it would be nice to have the result in chars array.

void init(const unsigned char *k) {
    uint64_t *kp = k;
    uint64_t sum = (*kp + *(kp+1)) % pow(2,64)
}

Thanks for help

+1  A: 

Hi,

I'm pretty sure that 2pow64 modulo naturally comes out of the precision of your data (64 bits in this case)

so create 2 variables integers, 64 bits precision, unsigned. called a, and b.

and move you first 4 bytes into a, 4 next bytes into b, add a to b.

In fact you just don't need to do modulo.

dzada
+7  A: 

You don't need the % pow(2,64), and in fact it introduces errors, since it will convert the result to and from double. Arithmetic in the type uint64_t is already modulo 2^64.

The issue of reading 8 bytes as a uint64_t is basically about what C implementations you want it to work on, and the format of the 8 bytes in your char array.

If you know that the 8 bytes in the char array have the same endian-ness as your system (that is, most significant byte first if your system is big-endian, most significant byte last if your system is little-endian), then what you're doing is probably OK. Whoever supplies the buffer will have to make sure that it's correctly aligned, though, if there are alignment restrictions for uint64_t on your system.

If the data came from some file or over the internet, then the endian-ness might not match the system, and it probably won't be aligned correctly.

If the 8 bytes are little-endian, this code would fail on a big-endian system, so if you wanted your code to be portable you'd have to do something else. There are systems where a unit64_t doesn't occupy 8 bytes, and even memcpy doesn't work. The specification of your function might mean that it's completely inapplicable to such systems, but in some circumstances it does make sense to convert an array of 8 char to a uint64_t, irrespective of whether actually CHAR_BIT is bigger than 8.

For a reliable basic solution: read one byte at a time and add the parts together (left-shifting by 0, then 8, and so on). If you don't like the look of that, make some assumptions about what platforms you need to support, and optimize.

However you read the data, if you want the result back in a char array then reverse the process - in the case of your code, *((uint64_t*)output_buffer) = kp[0] + kp[1];.

Steve Jessop
Thank you for the answer, the endian-ness is the same as my system. The solution with reading one byte and shifting works nice.
John
A: 

The problem is alignment. It can be that pointers to integers have to be properly aligned on your platform; the robust solution is to simply copy your bytes into temporary variables.

void init(const unsigned char *k) {
    uint64_t a, b; // two local variables 
    memcpy(&a,k,8); // fill them up
    memcpy(&b,k+8,8); // you presumably mean k+8?
    uint64_t sum = a + b;
    // do something with sum
}

You may also need to consider endianess; look at http://stackoverflow.com/questions/809902/64-bit-ntohl-in-c

Will
What about endianess?
drewk