You have no conditionals available but you can mask. There are different ways of creating a mask dependent on the value of the sign.
The following uses very nice tips by Eric Postpischil!
If the sign is 0 (ie positive) then the mask will become 0, else it is still the value you need -> conditional without conditional
#include <stdarg.h>
#include <stdio.h>
int sign2two(unsigned int a){
int sign = a>>31; // alternative: sign = !!((a<<1>>1)+~a+1); see below
unsigned int withoutSign = a << 1 >> 1;
unsigned int mask = ~sign +1;
printf("withoutSign is: %u\nsign is: %u\nmask is: %x\n",
withoutSign, sign, mask);
unsigned int temp = (withoutSign^mask)+sign;
return *(int*)&temp;
}
void printSign2two(unsigned int a){
printf("the 2s complement number: %i\n\n", sign2two(a));
}
int main(){
printSign2two(0x00000005);
printSign2two(0x80000005);
return 0;
}
output:
withoutSign is: 5
sign is: 0
mask is: 0
the 2s complement number: 5
withoutSign is: 5
sign is: 1
mask is: ffffffff
the 2s complement number: -5
Note about the sign = !!((a<<1>>1)+~a+1);
. This uses some more operators than sign = a>>31
but it is independent of 32/64 bitness.
<<1>>1
clears the most significant bit,
- we then want to check if it is different than the original. since
-a
is not allowed we use +~a+1
(thanks again Eric Postpischil)
- if there is no difference we already have the value 0 we want, else we have some huge number
- we then use !! to change the huge number to 1.