2

I am trying out this code where I first split a uint64 number into an array of uint8, followed by merging the said array back into the original number.

However when I attempt to print out the number out, it seems to return the max value of uint64.

uint8 buf[8];
uint64 test = 123456789012;
uint64 out = 0;

Uint64toUint8Arr(buf, test, 0);
out = Uint8ArrtoUint64(buf, 0);
std::cout << "out is " << out << std::endl;

where my functions are defined as:

void Uint64toUint8Arr (uint8* buf, uint64 var, uint32 lowest_pos)
{
    buf[lowest_pos]     =   (var & 0x00000000000000FF) >> 0 ;
    buf[lowest_pos+1]   =   (var & 0x000000000000FF00) >> 8 ;
    buf[lowest_pos+2]   =   (var & 0x0000000000FF0000) >> 16 ;
    buf[lowest_pos+3]   =   (var & 0x00000000FF000000) >> 24 ;
    buf[lowest_pos+4]   =   (var & 0x000000FF00000000) >> 32 ;
    buf[lowest_pos+5]   =   (var & 0x0000FF0000000000) >> 40 ;
    buf[lowest_pos+6]   =   (var & 0x00FF000000000000) >> 48 ;
    buf[lowest_pos+7]   =   (var & 0xFF00000000000000) >> 56 ;
}

uint64 Uint8ArrtoUint64 (uint8* var, uint32 lowest_pos)
{
    return  (var[lowest_pos+7] << 56) | 
            (var[lowest_pos+6] << 48) |
            (var[lowest_pos+5] << 40) | 
            (var[lowest_pos+4] << 32) |
            (var[lowest_pos+3] << 24) | 
            (var[lowest_pos+2] << 16) |
            (var[lowest_pos+1] << 8)  | 
            (var[lowest_pos]   << 0);
}

My question is that did I go wrong in either the way I split or merge the uint64 number? I did a similar function for a uint32 type and it seemed to be ok.

John Tan
  • 1,331
  • 1
  • 19
  • 35

1 Answers1

4

The problem is that you're shifting uint8 in Uint8ArrtoUint64() function on more than 8 bits. As far as I know it's undefined behavior. Anyway, return value is uint8, so you're "or'ing" eight times eight uint8 numbers and finally you have only uint8 number, not uint64! You need to cast them to uint64 first, then shift.

uint64 Uint8ArrtoUint64 (uint8* var, uint32 lowest_pos)
{
    return  (((uint64)var[lowest_pos+7]) << 56) | 
            (((uint64)var[lowest_pos+6]) << 48) |
            (((uint64)var[lowest_pos+5]) << 40) | 
            (((uint64)var[lowest_pos+4]) << 32) |
            (((uint64)var[lowest_pos+3]) << 24) | 
            (((uint64)var[lowest_pos+2]) << 16) |
            (((uint64)var[lowest_pos+1]) << 8)  | 
            (((uint64)var[lowest_pos])   << 0);
}

Note: As @interjay noted, shifting operation on uint8 will actually give us uint32. I'm not sure about that, but anyway it's better to mention it.

Community
  • 1
  • 1
Eldar Dordzhiev
  • 5,105
  • 2
  • 22
  • 26
  • 2
    The `uint8`s will actually be promoted to `int`, which is probably 32 bits. This explains why the 32 bit version seemed to work while the 64 bit version requires the casts. – interjay Sep 04 '14 at 15:32