Bit Level Operators - c

One of the few programming assignments I had due was dealing with bit level operators and I was hoping I did this correctly.
#include <stdio.h>
int main(void){
int x;
printf("Enter an x: ");
scanf("%x", &x);
printf("X = %d\n", x);
// Any bit in x is 1
x && printf("A bit in x is 1!\n");
// Any bit in x is 0
~x && printf("A bit in x is 0!\n");
// Least significant byte of x has a bit of 1
(x & 0xFF) && printf("A bit in least significant byte of x is 1!\n");
// Most significant byte of x has a bit of 0
int most = (x & ~(0xFF<<(sizeof(int)-1<<3)));
most && printf("A bit in the most significant byte of x is 0!\n");
return 0;
}
The assignment restricted what we could use so there could be no loops or conditionals and many other restrictions. I get a bit confused with the bit level operators so I was just hoping if there are any errors I could fix it and learn why it was wrong. Thanks.

You shouldn't use signed integers for these operations, because some cases result in undefined / implementation-defined behaviour: Arithmetic bit-shift on a signed integer
int most = (x & ~(0xFF<<(sizeof(int)-1<<3)));
You should negate x, not the right hand side:
int most = (~x & (0xFF<<(sizeof(int)-1<<3)));

Related

Different bits of two given integers

Hey so I have been asked to get the number of different bits between two integers.
I have written the code below which seem to work but only for positive numbers.
I would love to know what am I doing wrong.
printf("Enter 2 numbers:\n");
scanf("%d %d", &num1, &num2);
xor_num = num1 ^ num2;
while (xor_num != 0) {
if (xor_num & 1) {
xor_num = xor_num >> 1;
bits_on += 1;
}
else
xor_num = xor_num >> 1;
}
printf("There are %d diffrent bits\n", bits_on);
Shifting bits on a negative integer has implementation-defined behavior. In your case the sign bit (the most significant bit) is most likely not shifted so the variable xor_num never approaches zero and the loop is infinite. Instead you need to work on an unsigned integer. When you use the scanf function you also need to make sure that the input is valid. It is also a good idea to break out the code which calculates the number of bits into a separate function. Here is one way to do it:
#include <stdio.h>
#include <stdlib.h>
int BitCount(int x)
{
int result = 0;
unsigned int y = x;
while (y != 0) {
result += (y & 1);
y >>= 1;
}
return result;
}
int main(void)
{
int n, x, y;
printf("Enter 2 numbers:\n");
n = scanf("%d %d", &x, &y);
if (n == 2) {
printf("There are %d diffrent bits\n", BitCount(x ^ y));
} else {
fprintf(stderr, "wrong input\n");
exit(EXIT_FAILURE);
}
return 0;
}
When shifting negative values right, it is common for C implementations to copy the sign bit and leave it unchanged, rather than zeroing it. For example, where the four unsigned bits 1000 would be shifted to 0100 and then 0010 0001, and 0000, the four bits with a leading sign bit 1000 would be shifted to 1100, 1110, and then 1111. (The C standard leaves it to the implementation to define this behavior, per C 2018 6.5.7 5.) In this case, when xor_num is negative, xor_num >> 1 leaves the sign bit set, so it never becomes non-negative.
The easiest way to deal with this, presuming you are using int types, is to use unsigned xor_num = num1 ^ num2;. If your C implementation uses two’s complement do, which all regular implementations today do, the conversion from signed int to unsigned int will produce the same bits in xor_num but the shift with xor_num >> 1 will be a logical shift, which zeros the sign bit.

How to bit shift "x" with "y"?

I have some trouble with a bit-shift program.
The challenge is to write a program which can shift an unsigned int a number of steps to the left. Both integers are given as input by the user. Thus, given two integers (x and y), the bits in x shall be moved y steps to the left, and the bits which are lost on the left side should be moved to the right. Namely, the bits which are lost outside the most significant are placed in the least significant positions.
To solve the challenge, I have made the following attempt:
#include <stdio.h>
#include <utility.h>
unsigned int bitshift(unsigned int a, unsigned int b)
{
a<<b;
b>>a;
return a,b;
}
int main (void)
{
unsigned int x, y;
printf("Enter two integers (smaller than 32) please:\n");
scanf("%u%u", &x, &y);
printf("Your integers are %u and %u.\n", x, y);
printf("In hexadecimal-format, your integers are %08x and %08x.\n", x, y);
printf("We are now going to perform a bit shift operation\n");
printf("The result of the bitshift operation is:\n");
printf("%u and %u\n", bitshift(x,y));
printf("In hexadecimal: %08x and %08x\n", bitshift(x,y));
while(!KeyHit());
return 0;
}
However, I'm getting an error message when compiling, e.g. "not enough parameters", which I do not understand.
But what I am most wondering is if the bitshift function will do the job?
This is a modification of Barmar's (now deleted) solution for function bitshift with improvements suggested in comments.
Unfortunately, C does not have operators to rotate the bits in a value as might be available in the CPU's instruction set. That's why the operation can be done by moving the least significant bits to the left, moving the most significant bits to the right and combining the results.
To calculate the shift width for shifting the most significant bits to the right, the number of bits in the data type must be calculated using sizeof.
Note that a shift width greater than or equal to the number of bits in the value is undefined behavior (UB). That's why the shift width is calculated modulo the number of bits in the value. Additionally a left shift of 0 would result in UB in the right shift.
#include <stdio.h>
// get CHAR_BITS to make code portable for unusual platforms
#include <limits.h>
unsigned int bitshift(unsigned int a, unsigned int b)
{
// modulo operation to prevent undefined behavior
b %= sizeof a * CHAR_BIT; // sizeof a * 8 on usual platforms
// prevent undefined behavior for right shift
if(b == 0) return a;
unsigned int upper = a << b;
// not portable for unusual platforms
// unsigned int lower = a >> (sizeof a * 8 - b);
unsigned int lower = a >> (sizeof a * CHAR_BIT - b);
return upper | lower;
}
int main (void)
{
unsigned int x, y;
printf("Enter two integers (smaller than 32) please:\n");
scanf("%u%u", &x, &y);
printf("Your integers are %u and %u.\n", x, y);
printf("In hexadecimal-format, your integers are %08x and %08x.\n", x, y);
printf("We are now going to perform a bit shift operation\n");
printf("The result of the bitshift operation is:\n");
printf("%u\n", bitshift(x,y));
printf("In hexadecimal: %08x\n", bitshift(x,y));
return 0;
}
Example input/output:
Enter two integers (smaller than 32) please:
1234567890 12
Your integers are 1234567890 and 12.
In hexadecimal-format, your integers are 499602d2 and 0000000c.
We are now going to perform a bit shift operation
The result of the bitshift operation is:
1613571225
In hexadecimal: 602d2499
Enter two integers (smaller than 32) please:
246 28
Your integers are 246 and 28.
In hexadecimal-format, your integers are 000000f6 and 0000001c.
We are now going to perform a bit shift operation
The result of the bitshift operation is:
1610612751
In hexadecimal: 6000000f
It is enough tho shift right to get the bits which will be shifted out and or it with the value shifted left. To avoid UBs number of bits should be checked.
unsigned rol(unsigned val, unsigned nbits)
{
if(nbits && nbits < CHAR_BIT * sizeof(val))
{
val = (val >> (CHAR_BIT * sizeof(val) - nbits)) | (val << nbits);
}
return val;
}
You actually want to rotate the bits.
// Rotate the bits of a by b to the left and return the result
unsigned int bitshift(unsigned int a, unsigned int b)
{
for (unsigned int i = 0; i < b; i++)
{
unsigned int lowbit = 0;
if (a & 0x80000000)
lowbit = 1;
a <<= 1;
a |= lowbit;
}
return a;
}
This assumes unsigned int is 32 bits. You should be able to adapt it for 64 bits.
Disclaimer:
This is a very naive method though. If you need speed, you should avoid the loop. This can be done but it's more tricky.

Hex of most significant nibble

I am having trouble with bitwise manipulation.
To do: The hex value of the most significant nibble of x equals y (assume 0 <= y <= 15)
Restrictions: may not use equality (==) or inequality (!=) tests, relative comparison operators, division, modulus, and multiplication, conditionals.
Problem: I need to make my function so that when msb = y it returns 1 and if it is not true 0. However, I keep getting zero even when i run it with 0xff. If someone could point me in the right direction that would be great. Thank you.
int sig_nib(int x, int y){
int shifright = x >> 27;
int result = shifright & y;
return (result ^ y);
}
Silly restrictions. Who broke your compiler?
Something like this should do it:
bool sig_nib(int x, int y)
{
const int top4 = (x >> 28) & 0xf;
return !(top4 ^ y);
}
It uses Boolean inversion (!) to re-interpret the integer result from the bitwise-xor.

Bitwise operation and masks

I am having problem understanding how this piece of code works. I understand when the x is a positive number, actually only (x & ~mark) have a value; but cannot figure what this piece of code is doing when x is a negative number.
e.g. If x is 1100(-4), and mask would be 0001, while ~mask is 1110.
The result of ((~x & mask) + (x & ~mask)) is 0001 + 1100 = 1011(-3), I tried hard but cannot figure out what this piece of code is doing, any suggestion is helpful.
/*
* fitsBits - return 1 if x can be represented as an
* n-bit, two's complement integer.
* 1 <= n <= 32
* Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 2
*/
int fitsBits(int x, int n) {
/* mask the sign bit against ~x and vice versa to get highest bit in x. Shift by n-1, and not. */
int mask = x >> 31;
return !(((~x & mask) + (x & ~mask)) >> (n + ~0));
}
Note: this is pointless and only worth doing as an academic exercise.
The code makes the following assumptions (which are not guaranteed by the C standard):
int is 32-bit (1 sign bit followed by 31 value bits)
int is represented using 2's complement
Right-shifting a negative number does arithmetic shift, i.e. fill sign bit with 1
With these assumptions in place, x >> 31 will generate all-bits-0 for positive or zero numbers, and all-bits-1 for negative numbers.
So the effect of (~x & mask) + (x & ~mask) is the same as (x < 0) ? ~x : x .
Since we assumed 2's complement, ~x for negative numbers is -(x+1).
The effect of this is that if x is positive it remains unchanged. and if x is negative then it's mapped onto the range [0, INT_MAX] . In 2's complement there are exactly as many negative numbers as non-negative numbers, so this works.
Finally, we right-shift by n + ~0. In 2's complement, ~0 is -1, so this is n - 1. If we shift right by 4 bits for example, and we shifted all the bits off the end; it means that this number is representable with 1 sign bit and 4 value bits. So this shift tells us whether the number fits or not.
Putting all of that together, it is an arcane way of writing:
int x;
if ( x < 0 )
x = -(x+1);
// now x is non-negative
x >>= n - 1; // aka. x /= pow(2, n-1)
if ( x == 0 )
return it_fits;
else
return it_doesnt_fit;
Here is a stab at it, unfortunately it is hard to summarize bitwise logic easily. The general idea is to try to right shift x and see if it becomes 0 as !0 returns 1. If right shifting a positive number n-1 times results in 0, then that means n bits are enough to represent it.
The reason for what I call a and b below is due to negative numbers being allowed one extra value of representation by convention. An integer can represent some number of values, that number of values is an even number, one of the numbers required to represent is 0, and so what is left is an odd number of values to be distributed among negative and positive numbers. Negative numbers get to have that one extra value (by convention) which is where the abs(x)-1 comes into play.
Let me know if you have questions:
int fitsBits(int x, int n) {
int mask = x >> 31;
/* -------------------------------------------------
// A: Bitwise operator logic to get 0 or abs(x)-1
------------------------------------------------- */
// mask == 0x0 when x is positive, therefore a == 0
// mask == 0xffffffff when x is negative, therefore a == ~x
int a = (~x & mask);
printf("a = 0x%x\n", a);
/* -----------------------------------------------
// B: Bitwise operator logic to get abs(x) or 0
----------------------------------------------- */
// ~mask == 0xffffffff when x is positive, therefore b == x
// ~mask == 0x0 when x is negative, therefore b == 0
int b = (x & ~mask);
printf("b = 0x%x\n", b);
/* ----------------------------------------
// C: A + B is either abs(x) or abs(x)-1
---------------------------------------- */
// c is either:
// x if x is a positive number
// ~x if x is a negative number, which is the same as abs(x)-1
int c = (a + b);
printf("c = %d\n", c);
/* -------------------------------------------
// D: A ridiculous way to subtract 1 from n
------------------------------------------- */
// ~0 == 0xffffffff == -1
// n + (-1) == n-1
int d = (n + ~0);
printf("d = %d\n", d);
/* ----------------------------------------------------
// E: Either abs(x) or abs(x)-1 is shifted n-1 times
---------------------------------------------------- */
int e = (c >> d);
printf("e = %d\n", e);
// If e was right shifted into 0 then you know the number would have fit within n bits
return !e;
}
You should be performing those operations with unsigned int instead of int.
Some operations like >> will perform an arithmetic shift instead of logical shift when dealing with signed numbers and you will have this sort of unexpected outcome.
A right arithmetic shift of a binary number by 1. The empty position in the most significant bit is filled with a copy of the original MSB instead of zero. -- from Wikipedia
With unsigned int though this is what happens:
In a logical shift, zeros are shifted in to replace the discarded bits. Therefore the logical and arithmetic left-shifts are exactly the same.
However, as the logical right-shift inserts value 0 bits into the most significant bit, instead of copying the sign bit, it is ideal for unsigned binary numbers, while the arithmetic right-shift is ideal for signed two's complement binary numbers. -- from Wikipedia

How to represent negation using bitwise operators, C

Suppose you have 2 numbers:
int x = 1;
int y = 2;
Using bitwise operators, how can i represent x-y?
When comparing the bits of two numbers A and B there are three posibilities. The following assumes unsigned numbers.
A == B : All of the bits are the same
A > B: The most significant bit that differs between the two numbers is set in A and not in B
A < B: The most significant bit that differs between the two numbers is set in B and not in A
Code might look like the following
int getDifType(uint32_t A, uint32_t B)
{
uint32_t bitMask = 0x8000000;
// From MSB to LSB
for (bitMask = 0x80000000; 0 != bitMask; bitMask >>= 1)
{
if (A & bitMask != B & bitMask)
return (A & bitMask) - (B & bitMask);
}
// No difference found
return 0;
}
You need to read about two's complement arithmetic. Addition, subtraction, negation, sign testing, and everything else are all done by the hardware using bitwise operations, so you can definitely do it in your C program. The wikipedia link above should teach you everything you need to know to solve your problem.
Your first step will be to implement addition using only bitwise operators. After that, everything should be easy. Start small- what do you have to do to implement 00 + 00, 01 + 01, etc? Go from there.
You need to start checking from the most significant end to find if a number is greater or not. This logic will work only for non-negative integers.
int x,y;
//get x & y
unsigned int mask=1; // make the mask 000..0001
mask=mask<<(8*sizeoF(int)-1); // make the mask 1000..000
while(mask!=0)
{
if(x & mask > y & mask)
{printf("x greater");break;}
else if(y & mask > x & mask)
{printf("y greater");break;}
mask=mask>>1; // shift 1 in mask to the right
}
Compare the bits from left to right, looking for the leftmost bits that differ. Assuming a machine that is two's complement, the topmost bit determines the sign and will have a flipped comparison sense versus the other bits. This should work on any two's complement machine:
int compare(int x, int y) {
unsigned int mask = ~0U - (~0U >> 1); // select left-most bit
if (x & mask && ~y & mask)
return -1; // x < 0 and y >= 0, therefore y > x
else if (~x & mask && y & mask)
return 1; // x >= 0 and y < 0, therefore x > y
for (; mask; mask >>= 1) {
if (x & mask && ~y & mask)
return 1;
else if (~x & mask && y & mask)
return -1;
}
return 0;
}
[Note that this technically isn't portable. C makes no guarantees that signed arithmetic will be two's complement. But you'll be hard pressed to find a C implementation on a modern machine that behaves differently.]
To see why this works, consider first comparing two unsigned numbers, 13d = 1101b and 11d = 1011b. (I'm assuming a 4-bit wordsize for brevity.) The leftmost differing bit is the second from the left, which the former has set, while the other does not. The former number is therefore the larger. It should be fairly clear that this principle holds for all unsigned numbers.
Now, consider two's complement numbers. You negate a number by complementing the bits and adding one. Thus, -1d = 1111b, -2d = 1110b, -3d = 1101b, -4d = 1100b, etc. You can see that two negative numbers can be compared as though they were unsigned. Likewise, two non-negative numbers can also be compared as though unsigned. Only when the signs differ do we have to consider them -- but if they differ, the comparison is trivial!

Resources