I need to do an Ultra High Performance swap of two pointers in C (the addresses, not what they point to). I know that the addresses are aligned (multiple of 16) and consecutive and I've already checked that this preserves in every execution. The code is as follows:
Nodo a __attribute__((aligned(8))), b __attribute__((aligned(4)));
Nodo *nodo_superior __attribute__((aligned(4)));
nodo_superior = &a;
Nodo * nodo_actual __attribute__((aligned(4)));
nodo_actual=&b;
printf("%ld %ld\n", nodo_superior, nodo_actual);
and the result on console is like (please, note that the first address should be "over"-aligned in order the next method to work):
140594404335200 140594404335216
Now to swap the addresses, I want to change the bit 5 of each pointer:
nodo_superior ^= 16;
nodo_actual ^= 16;
but, unfortunately the C compiler does not allow this because integers can not be mixed with pointer values: it's an error, not a warning. If I try to include the pointer in an union like this:
union {
Nodo * nodo_actual;
int local_int;
} na;
with the idea of doing an assigment like:
na.local_int ^= 16;
then the performance decreases because (I suppose) the compiler cannot apply/infer optimizations to nodo_actual if it is in an union. Any ideas to force the compiler to behave as I want? Of course, I could change the generated assembler but I do not consider it a good option,
If you want to toggle the bit 5 of each pointer you can write:
uintptr_t
is an integer type that (if exists) is guaranteed to be able to hold a pointer value without loss of information.It's intended that this be done by the obvious isomorphism on a flat memory model, so it should work for you (although test it first to see).
Also, you should be using
%p
to printf a pointer, not%ld
which causes undefined behaviour. To printuintptr_t
see here