0

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?

Community
  • 1
  • 1
Perlator
  • 241
  • 1
  • 2
  • 11
  • What is the type of the `upub`? You are possibly violating strict aliasing rules. – user694733 May 05 '17 at 13:18
  • Why do you assume it is too slow? Did you hav a look at the assembly code? Did you profile? Concentrate on writing portable and readable code in the first place (e.g. by wrapping this in a function), optimise only if you have a speed issue. – too honest for this site May 05 '17 at 13:25
  • I do have a speed issue and I am aware of the "premature optimization problem". Doesn't apply here. My assumtion was based purely on intuition, but benchmarked against `*((uint64_t *) upub + 33) = __builtin_bswap64(some64bitval);` my intuition proved to be right. – Perlator May 05 '17 at 13:36

3 Answers3

3

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.

Community
  • 1
  • 1
ilkkachu
  • 6,221
  • 16
  • 30
  • What is `upub`? Depending how is is declared/set up, this can and will invoke UB. – too honest for this site May 05 '17 at 13:26
  • @Olaf, we don't know, the question doesn't tell. I thought I mentioned that the information is missing, and I also thought I mentioned the possible aliasing issue? I'd be happy to see a verification on the subject one way or the other. – ilkkachu May 05 '17 at 13:35
  • upub/carr is **as the title says** a `uchar`/`uint8_t` array. `*(uint64_t *) (upub+33) = __builtin_bswap64(PplusQ[di][3]);` works perfectly with all warnings, pedantic and other whistles enabled. It is also faster than the original code. – Perlator May 05 '17 at 13:38
  • @ilkkachu UB is not just aliasing! You might be surprised what can happen if you violate the effective type rule. – too honest for this site May 05 '17 at 13:54
1

You can copy as:

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

assuming upub is pointer variable

Pras
  • 4,047
  • 10
  • 20
1

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.

Lundin
  • 195,001
  • 40
  • 254
  • 396