Search code examples
carraysint64

copy byte-reversed uint64_t to uint8_t array


I know how to reverse the byte order (convert big endian to little endian in C [without using provided func]) - in this case I'd like to use __builtin_bswap64

I also know how to copy a 64bit uint to a char array - ideally memcopy. (How do I convert a 64bit integer to a char array and back?)

My problem is the combination of both these. At the root of the problem, I'm trying to find a faster alternative to this code:

carr[33] = ((some64bitvalue >> 56) & 0xFF) ;
carr[34] = ((some64bitvalue >> 48) & 0xFF) ;
carr[35] = ((some64bitvalue >> 40) & 0xFF) ;
carr[36] = ((some64bitvalue >> 32) & 0xFF) ;
carr[37] = ((some64bitvalue >> 24) & 0xFF) ;
carr[38] = ((some64bitvalue >> 16) & 0xFF) ;
carr[39] = ((some64bitvalue >> 8) & 0xFF) ;
carr[40] = (some64bitvalue & 0XFF);

As memcopy doesn't take the result of __builtin_bswap64 as source argument (or does it?), I tried this:

*(uint64_t *)upub+33 = __builtin_bswap64(some64bitvalue);

but I end up with the error: lvalue required as left operand of assignment

Is there a faster alternative to the original code I'm trying to replace at all?


Solution

  • This:

    *(uint64_t *)upub+33 = __builtin_bswap64(PplusQ[di][3]);
    

    parses as

    (*(uint64_t *) upub) + 33 = __builtin_bswap64(PplusQ[di][3]);
    

    so the left-hand side is a uint64_t, not an lvalue.

    So would this work?

    *(uint64_t *) (upub+33) = __builtin_bswap64(PplusQ[di][3]);
    

    or did you mean to cast upub to uint64_t * first, as Aconcagua commented?

    *((uint64_t *) upub + 33) = __builtin_bswap64(PplusQ[di][3]);
    

    I didn't see the type of upub mentioned, so I can't tell.

    Also, I have a feeling that there may be an issue with the aliasing rules if upub is originally pointing to another type, so you may want to use something like gcc's -fno-strict-aliasing or make the assignment through a union, or one byte at a time as in your first code snippet.