Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reverse bytes for 64-bit value

I'm trying to reverse the bytes for a 64 bit address pointer for an assignment and have this code:

char swapPtr(char x){
x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32;
x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
x = (x & 0x00FF00FF00FF00FF) << 8  | (x & 0xFF00FF00FF00FF00) >> 8;
return x;
}

But, it just messes everything up. However, a similar function works perfectly for a 64bit long. Is there something different that needs to be done for pointers?

Could the way I'm making the function call be an issue?

For a pointer:

*(char*)loc = swapPtr(*(char*)loc);

For a long:

*loc = swapLong(*loc);
like image 411
nix Avatar asked Feb 02 '14 06:02

nix


1 Answers

You cannot use char x for a pointer!!!! A char is only a single byte long.

You need at the very least

unsigned long int swapPtr(unsigned long int x) {

Or better, use the type of the pointer

void* swapPtr(void* x) {

Quite likely your compiler will complain when you start bit shifting pointers; in that case you're better off explicitly casting your argument to an unsigned 64 bit integer:

#include <stdint.h>
uint64_t x;

Note also that you have to call with the address of a variable, so you call with

result = swapLong(&loc);

not *loc (which looks at the place where loc is pointing - the value, not the address).

Complete program:

#include <stdio.h>
#include <stdint.h>

uint64_t swapLong(void *X) {
  uint64_t x = (uint64_t) X;
x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32;
x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
x = (x & 0x00FF00FF00FF00FF) << 8  | (x & 0xFF00FF00FF00FF00) >> 8;
return x;
}

int main(void) {
  char a;
  printf("the address of a is 0x%016llx\n", (uint64_t)(&a));
  printf("swapping all the bytes gives 0x%016llx\n",(uint64_t)swapLong(&a));
}

Output:

the address of a is 0x00007fff6b133b1b
swapping all the bytes gives 0x1b3b136bff7f0000

EDIT you could use something like

#include <inttypes.h>

printf("the address of a is 0x%016" PRIx64 "\n", (uint64_t)(&a));

where the macro PRIx64 expands into "the format string you need to print a 64 bit number in hex". It is a little cleaner than the above.

like image 130
Floris Avatar answered Sep 27 '22 17:09

Floris