简体   繁体   中英

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?

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.

You can copy as:

uint64_t tmp = __builtin_bswap64(some64bitvalue);
memcpy(upub+33,&tmp,sizeof(tmp));

assuming upub is pointer variable

When writing endian-independent code there is no alternative to bit shifts. You code is likely already close to ideal.

What you could play around with is to use a loop instead of hard-coded numbers. Something along the lines of this:

for(uint_fast8_t i=0; i<8; i++)
{
  carr[i+offset] = (some64bitvalue >> (56-(i*8)) & 0xFF;
}

This may turn slower or faster or equal compared to what you already have, depending on the system. Overall, it doesn't make any sense to discuss manual optimization like this without a specific system in mind.

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