how do I set up an if statement - c

How would I go about setting up an if statement using only the following bitwise operations:
!
~
&
^
|
+
<<
>>
As an example: "if x is negative then add 15"
This would mean that if the input was x = 0xF0000000, then we would produce 0xF000000F. If the input was x = 0x00000004, we would produce 0x00000004.

You can add 15 to a number if it is negative, and 0 otherwise as follows. Shifting a negative number right will shift in 1's if the value is negative, and 0's otherwise. Shifting by 31 will fill the int with either 1's or 0's. ANDing by 0xF will set the summand to 15 if it is negative, and 0 otherwise, resulting in no change to x.
x += (x >> 31) & 0xF;
If you're worried about the implementation dependent behavior of shifting a signed number to the right. You can do the same thing with the following code, however you still are depending on a two's complement representation of the number. The shift results in 0 or 1, the multiplication scales the number to the appropriate value.
x += (((unsigned)x >> 31) * 0xF);

Related

Value of x when s = x >> 31 and x = (s & ~x) | (~s & x);

If x was to equal 12 in a 32 bit scenario, x = multiple 0's into the lsb 0000 1100. If the above scenario were to run, I believe I would get 0000 1100. Am I wrong?
Along with that, what if I was to use x=-1? Wouldn't s = 1, but then does (s & ~x) look like (0001 & 0000) and (1110 & 1111)? Thanks
I thought that x=-1 would mean x>>31 would be like 0001 (output 1), but I don't know if the above is correct.
The typical implementation of a right shift of a signed integer is an arithmetic shift. Different implementations are unfortunately still allowed, though rare, and they're not relevant to understanding this code (it ignores such possibilities anyway). Two's complement integers are now mandatory (in C23: "The sign representation defined in this document is called two’s complement. Previous revisions of this document
additionally allowed other sign representation") so I'm not going to do the usual consideration of hypothetical integer representations that haven't been seen since the stone age.
By assumption the number of bits in an int is 32, so shifting an int right by 31 makes every bit of the result a copy of the sign bit. So if x was negative, s would be -1.
x = (s & ~x) | (~s & x) is a verbose way to spell out x ^= s. XORing x by 0 leaves it the same as before, XORing it by -1 inverts all the bits. Taking into account that s = x < 0 ? -1 : 0, effectively the computation does this:
if (x < 0)
x = ~x; // equivalent to: x = -x - 1;

What do these 3 lines of C code do by themselves, and what do they do altogether?

int mystery(int x) {
int mask = x >> 31;
return (x ^ mask)
+ ~mask + 1L;
I believe the first line creates a mask from x, such that it is all 1s if the most significant bit is 1, and all 0s if the MSB is 0.
The second line XORs the mask with the original x, which flips all the bits if the mask is 1s, and does nothing if the mask is all 0s.
Then the third line adds the complement of the mask, and also adds 1L... this is where I don't understand.
So my question is, what does the 3rd line do specifically, particularly the 1L?
And what does the entire function do to x?
This is returning the absolute value of a number without branching on a two's complement machine. However, there is one important exception: if x is originally INT_MIN, this will return INT_MIN.
Let's take a number -3 as an example and step through this.
int mask = x >> 31; defines a variable called mask that is -1 (or all bit if x was originally negative (not portable!) and 0 otherwise. With x as -3 mask is -1.
(x ^ mask) is the value of x with all bits flipped if x was originally negative. The result of this expression is 2 if x was originally -3.
+ ~mask + 1L; adds the result of the above to 1 if x was negative or 0 otherwise and returns it. The result would be 3 if x was originally -3.
To explain this step further, let's consider when mask is -1. The ~ will flip all the bits to 0. After that, adding 1 causes this to, well, add 1 to the result.
Considering when mask is 0, the ~ flips all the bits to 1 (which is -1) and then adds 1, so the result would be no change.
Let's also step through the INT_MIN scenario:
mask is -1.
flip all bits of INT_MIN is INT_MAX.
adding 1 to INT_MAX is INT_MIN (and undefined behavior!!!).
Now let's see what happens with a positive x. Using 5 as an example:
mask is 0.
x is left unchanged.
x is again left unchanged.
Unless you're using a compiler that defines all of this behavior, this won't work. I highly suggest against using this.
The function returns the absolute value of a number.
(x ^ mask) will flip the bits of the number if mask is all 1's (the number is initially negative).
~mask + 1L; will evaluate to either -1 + 1 or 0 + 1 depending on if mask is all 0s or 1s respectively.
Putting it all together, this means that when the number is negative, we flip the bits and add 1. When the number is positive, we don't flip the bits and add 0 (keep it the same). This converts a negative number to a positive number because of how computers store negative numbers. You can read further about this by looking up "two's compliment"
Assuming x is a 32-bit integer with the sign in the 32th (leftmost) bit,
int mask = x >> 31;
"mask" holds now either -1 (if x was negative) or 0. If it is -1, its binary representation is 0xffffffff (all 1's).
return (x ^ mask)
So x^mask is x XORed with either all 0s (remaining unchanged) or all 1's, including sign, which will invert its sign and map it to the positive value one less than the original. So 42 will remain 42, but -42 will become 41.
+ ~mask
not-mask will be 0 if x is negative, or all 1's, i.e. 0xffffffff (hence -1) if x was positive. Adding it, 42 will yield 41, and -42 (which was transformed to 41) will remain 41. Note that now in both cases we have the same number.
+ 1L;
Now, 42 (which was changed to 41) will become back 42, while -42 (which was 41) will become 42. The L is superfluous, as 1 alone will be taken as an int.
All in all, the function will return a value if it's positive, its opposite (i.e. its absolute value) if not.
NOTE: this function will obviously fail if its argument is the minimum (maximally negative) number, as that number has no positive representation in the same space as integers. So, mystery(-2147483647) will yield 2147483647 as expected, but mystery(-2147483648) will yield -2147483648.
Chances are very good that you'll fare better by using abs() instead of your mystery function, which could be an abs implementation for some architectures, while abs tends to be the best implementation for each architecture it's compiled for.
I believe it's supposed to return the absolute value of its argument, but it has a bug: if the argument passed in is 0x8000000 then it returns its argument. Test code:
#include <stdio.h>
int mystery(int x) {
printf("x=%d (0x%X)\n", x, x);
int mask = x >> 31;
printf("mask=%d (0x%X)\n", mask, mask);
printf("(x ^ mask)=0x%X\n", x ^ mask);
printf("~mask=0x%X\n", ~mask);
int retval = (x ^ mask) + ~mask + 1L;
printf("retval=%d (0x%X)\n\n", retval, retval);
return retval;
}
int main()
{
mystery(1);
mystery(0);
mystery(-1);
mystery(0x80000000);
}
All I've done is break up the calculation and print the intermediate results. For the calls shown this produces:
x=1 (0x1)
mask=0 (0x0)
(x ^ mask)=0x1
~mask=0xFFFFFFFF
retval=1 (0x1)
x=0 (0x0)
mask=0 (0x0)
(x ^ mask)=0x0
~mask=0xFFFFFFFF
retval=0 (0x0)
x=-1 (0xFFFFFFFF)
mask=-1 (0xFFFFFFFF)
(x ^ mask)=0x0
~mask=0x0
retval=1 (0x1)
x=-656 (0xFFFFFD70)
mask=-1 (0xFFFFFFFF)
(x ^ mask)=0x28F
~mask=0x0
retval=656 (0x290)
x=-2147483648 (0x80000000)
mask=-1 (0xFFFFFFFF)
(x ^ mask)=0x7FFFFFFF
~mask=0x0
retval=-2147483648 (0x80000000)

bitwise shift with logical OR in C

My original code to take x and turn it into the largest negative int was
*x = 1 <<31 | ~ 1<<31;
which works but when I tried just using
*x = 1 <<31;
It returned the same answer can someone explain why this is so?
If your int is on 32 bits on your architecture, the largest negative int value is obviously 0x80000000.
Let's look at your code and add parenthesis to show the precedence of operators (this is the key here):
*x = 1 <<31 | ~ 1<<31 = (1 << 31) | ((~1) << 31)
The evaluation of the expression ((~1) << 31) gives the result 0x00000000.
So the final result is 1 << 31 = 0x80000000.
Well if you know two's complement, then you know that for a 32 bit integer, 0x80000000 must be the largest negative value, because if you flip the bits and add one from 0x80000000, you get 0x7fffffff. add one and you get 0x80000000, the largest negative number possible with 32 bits. This has a 1 in the MSB, and there is no way to get larger than this, given that the initial number needs to save a bit for the sign. Your original code just fills the int with 1's and then shifts over 31 resulting in the same final value as *x = 1 <<31;

C expression that sets the last n bits of int variable to zero

In other words, sets the last 5 bits of integer variable x to zero, also it must be in a portable form.
I was trying to do it with the << operator but that only moves the bits to the left, rather than changing the last 5 bits to zero.
11001011 should be changed to 11000000
Create a mask that blanks out that last n integers if it is bitwise-ANDed with your int:
x &= ~ ((1 << n) - 1);
The expression 1 << n shifts 1 by n places and is effectively two to the power of n. So for 5, you get 32 or 0x00000020. Subtract one and you get a number that as the n lowest bits set, in your case 0x0000001F. Negate the bits with ~ and you get 0xFFFFFFE0, the mask others have posted, too. A bitwise AND with your integer will keep only the bits that the mask and your number have in common, which can only bet bits from the sixth bit on.
For 32-bit integers, you should be able to mask off those bits using the & (bitwise and) operator.
x & 0xFFFFFFE0.
http://en.wikipedia.org/wiki/Bitwise_operation#AND
You can use bitwise and & for this
int x = 0x00cb;
x = x & 0xffe0;
This keeps the higher bits and sets the lower bits to zero.

Convert two's complement to sign-magnitude

I need to convert from two's complement to sign-magnitude in C using only the operators
! ~ & ^ | + << >>
My approach is to find sign:
int sign = !(!(a>>31));
basically, if sign == 1 . I want to flip the number and add 1 else just want to display the number.
The thing is I can't use any loops, if statements etc.
This is what I'm working on:
int s_M = ((((a+1)>>31)^sign)+1)&sign;
any suggestions?
From http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs
int const mask = v >> 31;
unsigned int r = (v + mask) ^ mask;
Gives the absolute value (magnitude). If you wish to add the sign bit back simply mask and or the 32nd bit:
unsigned int s_M = r | (v & 0x80000000);
Or if you're looking for a one liner:
unsigned int s_M = ((v + (v >> 31)) ^ (v >> 31)) | (v & 0x80000000);
When you're converting from 2 complement, you should subtract 1, not add.
I'm not entirely sure what the output should be, but to obtain the magnitude you can do something like this:
int m = (a^(a>>31)) + sign;
Basically, shifting a negative number 31 bits to the right will make it all 1's, or 0xffffffff, which you can then use to xor the input number and make it positive. As you correctly noted sign needs to be added then for the correct result in that case.
If the input number was positive to begin with, the shift results in a zero and so the xor does nothing. Adding sign in that case also doesn't do anything, so it results in the input number.
To get the last bit you could use mask operation
int last_bit = 32 bit integer & 0x80000000
o/p may be 0 or 0x80000000
if it is 0 just display the given number else you have to perform the following operations to represent in signed magnitude
1) Subtract 1 from the number
2) perform 1s complement on the resultant ( that is negation ~)
3) Set the last bit of the resultant number
I mean ( ~ (num -`1) ) | 0x7fffffff
since your restricted not to use - operator. Perform the 2's complement on -1 and add it to the num.
To put it simple in one line
num & 0x80000000 ? printf("%d",(~(num+((~1)+1))) | 0x7fffffff) : printf("%d",num) ;

Resources