Combining three bits to get a single integer value - c

So I have three variables each hold a 1 or a 0. These three form an address 0 - 7 when combined. for example
var1 = 1;
var2 = 0;
var3 = 1;
would be 5.
How would I go about combining these three variable to get an integer value? I have heard bit shifting operations would be the best way but I'm not sure how to do it. thanks.

Make sure the values are 0 or 1 for safety: AND with 1 do this
move these 0/1 values to proper positions: done with << operator
combine them: OR these values
if var1 = 1; var2 = 0; var3 = 0 should be 4, use this:
((var1 & 1) << 2) | ((var2 & 1) << 1) | (var3 & 1)
if var1 = 1; var2 = 0; var3 = 0 should be 1, use this:
((var3 & 1) << 2) | ((var2 & 1) << 1) | (var1 & 1)

var1 = 1, var2 = 0, var3 = 1, var4 = 1, var5 = 0, var6 = 0, var7 = 1, var8 = 0
byte = (var1<<7)+(var2<<6)+(var3<<5)+(var4<<4)+(var5<<3)+(var6<<2)+(var7<<1)+var8;
value of byte is 10110010

This works:
You shift the first bit 2 bits to the left with << 2, the second bit 1 bit to the left with << 1 and leave the last bit as it's in the last place.
That gives you 3 variables which are now 100, 000 and 001, You then or them together with | to get 101 i.e. 5.
I.e.
v1 is currently 001 in binary and you want it to be the 3rd bit, I.e. 100, so you need to shift it 2 to the left (v1 << 2)
Likewise, v2 is currently 000, and you want the 0 to be the 2nd bit, so you shift it 1 to the left (v2 << 1) to give 000 (trivial in this case but obviously different with a 1 here).
Finally, v3 is 001 and you want it to be the 3rd bit... It already is so we can leave it where it is.
Finally to combine them, we or the values together with |
100 |
000 |
001 =
101 = 5 in binary
#include <stdio.h>
#include <stdlib.h>
int main()
{
int v1=1, v2=0, v3=1;
int result;
result = (v1 << 2) | (v2 << 1) | v3;
printf("%d\n", result);
return 0;
}

In order to get a true answer you need to define what variable belongs to what bit position in the binary number you're trying to calculate and make sure you set the value of each variable to either zero or one or you'll be shifting the wrong bits around in the result.
In the code example below, the order of bits read from left to right is var3, var2, var1. var3 is known as the most significant bit, and var1 is known as the least significant bit.
If you want the value of 1, you set var1 to 1, then var2 and var3 to 0.
If you want the value of 4, you set var1 and var2 to 0 then set var3 to 1.
If you want the value of 5, you set var1 and var3 to 1 then set var2 to 0.
#include <stdio.h>
#include <stdlib.h>
int main(void){
int var1=1;
int var2=0;
int var3=1;
int res=(var3 << 2) + (var2 << 1) + var1;
printf("%d\n",res);
return 0;
}
If you want a somewhat easier-to-understand version, you can use this code:
#include <stdio.h>
#include <stdlib.h>
int main(void){
int LeastSignificantBit=1;
int MiddleBit=0;
int MostSignificantBit=1;
int Number=0;
Number=(MostSignificantBit << 2) + (MiddleBit << 1) + (LeastSignificantBit << 0);
printf("Number is %d\n",Number);
return 0;
}
I understand using << 0 is overkill, but I'm illustrating the fact that the least significant bit doesn't need to be shifted over.

When you bit shift some number you will just go from right to left on the memory. So, as we know, if we shift the number to the left it'll be multiplied by 2, since the base of the computer is binary. If we shift to the right, it'll be divided by 2.
like this:
decimal 5 --> binary 00101
decimal 10 --> binary 01010
Note that we've just shifted once to the left and we have the result of 5 multiplied by 2, therefore 10.
In your code I suggest you receive the variables by an scanf, the proceed to shift those and then sum them, like so:
#include <stdio.h>
int main(){
int var1, var2, var3;
scanf("%d %d %d", &var1, &var2, &var3);
printf("%d\n", (var1 << 2) + (var2 << 1) + var3);
return 0;
}
The code above we put the variable__<<__number_of_shifts. So in the first one we shift the var1 twice, the second one we shift once and at the last one we shift none. Then we sum all together and have your answer!

If the input variables are guaranteed to have value 1 or 0 then:
address = (var1 << 2) | (var2 << 1) | var3 ;
will do exactly what you want; however given that var1 etc. are integers an invalid and likely out-of-range address will be generated if the preconditions are not checked or limited.
A more flexible and maintainable implementation that allows simple address range extension would be to use an array rather than three separate variables. The fact that you numbered then in the first place rather suggests an array might be appropriate in any case):
#define ADDR_BITLEN 3
unsigned var[ADDR_BITLEN] ;
...
unsigned address = 0 ;
for( int bit = ADDR_BITLEN - 1; bit >= 0; bit++ )
{
address |= ((var[bit] == 0) ? 0 : 1) << bit ;
}
Now any number of bits up-to the bit length of an unsigned may be used for address simply by changing ADDR_BITLEN, further more the loop body ensures that an invalid address is not generated if address_bits[bit] is > 1 by selecting 0 or 1 explicitly, which would be somewhat cumbersome and hard to read and maintain if the array and loop were not used.

Related

How to extract bits from a number in C?

I need to extract specific part (no of bits) of a short data type in C.
Fox example, i have a binary of 45 as 101101 and i just want 2 bits in middle such as (10)
I started with C code 2 days ago so don't given a lot of functions.
How do i extract them ?
Please search for bit-wise operations for more general information, and bit masking for your specific question. I wouldn't recommend to jump to bits if you are new to programming though.
The solution will slightly change depending on whether your input will be fixed in length. If it won't be fixed, you need to arrange you mask accordingly. Or you can use a different method, this is probably simplest way.
In order to get specific bits that you want, you can use bitmasking.
E.g you have 101101 and you want those middle two bits, if you & this with 001100, only bits that are 1 on the mask will remain unchanged in the source, all the other bits will be set to 0. Effectively, you will have those bits that you are interested in.
If you don't know what & (bitwise and) is, it takes two operands, and returns 1 only if first AND second operands are 1, returns 0 otherwise.
input : 1 0 1 1 0 1
mask : 0 0 1 1 0 0
result : 0 0 1 1 0 0
As C syntax, we can do this like:
unsigned int input = 45;
unsigned int mask = 0b001100; // I don't know if this is standard notation. May not work with all compilers
// or
unsigned int mask = 12; // This is equivalent
unsigned int result = input & mask; // result contains ...001100
As yo can see, we filtered the bits we wanted. The next step depends on what you want to do with those bytes.
At this point, the result 001100 corresponds to 12. I assume this is not really useful. What you can do is, you can move those bits around. In order to get rid of 0s at the right, we can shit it 2 bits to the right. For this, we need to use >> operator.
0 0 1 1 0 0 >> 2 ≡ 0 0 0 0 1 1
result = result >> 2; // result contains ...011
From there, you can set a bool variable to store each of them being 1 or 0.
unsigned char flag1 = result & 0b01; // or just 1
unsigned char flag2 = result & 0b10; // or just 2
You could do this without shifting at all but this way it's more clear.
You need to mask the bits that you want to extract. If suppose you want to create mask having first 4 bits set. Then you can do that by using:
(1 << 4) - 1
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
void print_bin(short n)
{
unsigned long i = CHAR_BIT * sizeof(n);
while(i--)
putchar('0' + ((n >> i) & 1));
printf("\n");
}
int main()
{
short num = 45; /* Binary 101101 */
short mask = 4; /* 4 bits */
short start = 0; /* Start from leftmost bit
position 0 */
print_bin((num >> start) & ((1 << mask) - 1)); /* Prints 1101 */
mask = 2; /* 2 bits */
start = 1; /* start from bit indexed at position 1 */
print_bin((num >> start) & ((1 << mask) - 1)); /* Prints 10 */
return 0;
}
Output:
0000000000001101
0000000000000010

Trailing Zeros - C

I need a program that returns the number of trailing zeros in the binary rapresentation of a number. I found online a function written in C but I don't understand how it works
This is the function:
unsigned tzr(unsigned x)
{
unsigned n; /* number of bits */
n = 0;
if (!(x & 0x0000FFFF)) { n += 16; x >>= 16; }
if (!(x & 0x000000FF)) { n += 8; x >>= 8; }
if (!(x & 0x0000000F)) { n += 4; x >>= 4; }
if (!(x & 0x00000003)) { n += 2; x >>= 2; }
n += (x & 1) ^ 1; // anyway what does this do ?
return n;
}
Now I've really tried to understand how this works but I don't get it.
I really need someone who could explain it to me, I find this code very complicated.
And about those hexadecimal constants, these are their values:
0x0000FFFF = 65535
0x000000FF = 255
0x0000000F = 15
0x00000003 = 3
Now, why the program uses those values and makes a bitwise AND with the number?
Then I know that if you want to handle big numbers you must
use a while instead of the first if statement, like this:
while (!(x & 0x0000FFFF)) { bits += 16; x >>= 16; } // why should I need this ?
But I don't know why ! What's the difference about using a while instead of an if in this case?
The hexadecimal constants are AND'ed with the value to check whether the last [number] of digits is zero.0x0000FFFF is a number with 16 ones in binary. If the value AND'ed with 0x0000FFFF is equal to 0, you know that the last 16 digits are zeroes (the ifs check for the reverse of that statement). Going further 0x000000FF is a number with 8 ones in binary. The next check is for the last 8 digits, next for 4 digits and the last one for 2 digits as 0x00000003 is 11 in binary. After the checks the numbers are shifted to check whether further digits are also zero. This way we can check for any number of trailing zeroes as the values are powers of 2 and adding them works exactly like working with binary.
Last statement checks for the last digit after all the previous shifting is done - AND with 1 and checking if it's 0 or 1 with a XOR(^).
This program checks numbers with 32 bits. You can change the first if to a while to check larger, e.g. 64-bit, numbers. Another way is to check with 0xFFFFFFFF and then shift 32 bits at once.
The line n += (x & 1) ^ 1 checks the least significant bit (LSB) of the current state of x. If the LSB is a 1 then (x & 1) yeilds 1 which is then XORed (the caret symbol '^' means to XOR two values) with 1 to give 0 (1 ^ 1 == 0). When x has a 0 in the LSB and is XORed with 1 it yeilds 1 (0 ^ 1 == 1).
!(x&0x0000FFFF) will be true only when the last 16 bits of x are all 0's.
The & is a bitwise and, and 0x0000FFFFF is the number ending in 16 1's.
So the result of the and is 0 iff all 16 trailing bits are 0 (and so FALSE and 1 reverses the truth value) because if there is at least one 1 among the last 16, the and with the corresponding 1 in the constant will be 1. So then the and is not 0 (so TRUE and ! reverses the truth value).
So the code says: if the last 16 bits are 1, add 16 to n and throw the last 16 bits away (that is what x >>= 16 does).
The next line says in a similar way:
if the last 8 bits of the (possibly shortened x) are 0 ,add 8 to n and throw the rightmost 8 bits away, and so on for 4 and 2 bits as well
The last line adds 1 if the rightmost bit (x&1) is 0, otherwise 0 (1^1 = 0).
So say if the righmost 15 bits are 0, the first if will be false , n remains 0.
The second will be true, as we have more than 8. Tne new x will have 7 0-bits,
and n=8.
The third will also be true (we have still 4 or more), so the new x has 3 0-bits after the shift and n=12.
The fourth will also be true (2 or more 0's) so the new x has 1 0-bit and n=14.
The final statement adds 1, so get n=15.
Because we use decreasing powers of 2 we don't need a loop. We get all possible n values this way (except 32, for input x=0, a fully correct function should maybe check for that and early abort.
n += (x & 1) ^ 1; // anyway what does this do ?
This checks the right-most bit. Either it is set or NOT set.
If it is set, then there is NOT another 0 to add onto the running total of trailing zeros, so n+=0.
If it is NOT set, then there is another 0 to add onto the running total of trailing zeros, so n+=1.
Also, your example does NOT compile, it is missing two ; as follows:
unsigned tzr(unsigned x)
{
unsigned n; /* number of bits */
n = 0;
if (!(x & 0x0000FFFF)) { n += 16; x >>= 16; }
if (!(x & 0x000000FF)) { n += 8; x >>= 8; }
if (!(x & 0x0000000F)) { n += 4; x >>= 4 } // won't compile due to missing ;
if (!(x & 0x00000003)) { n += 2; x >>= 2 } // won't compile due to missing ;
n += (x & 1) ^ 1; // anyway what does this do ?
return n;
}
Also, you can always try printing out data, for example, every power of 2 has multiple trailing zeros, but only odd amounts of trailing zeros are incremented by an additional 1 from n += (x & 1) ^ 1;...
cout << tzr(9) << endl << endl; // 1001 (not a power of two )
cout << tzr(8) << endl << endl; // 1000 (8>>2 & 1)^1==1
cout << tzr(4) << endl << endl; // 0100 (4>>2 & 1)^1==0
cout << tzr(2) << endl << endl; // 0010 ( 2 & 1)^1==1
cout << tzr(1) << endl << endl; // 0001 ( 1 & 1)^1==0
tzr(9) == 0 ==> 0 + (9 & 1) ^ 1 == 0 + 0
tzr(8) == 3 ==> 2 + (8>>2 & 1) ^ 1 == 2 + 1
tzr(4) == 2 ==> 2 + (4>>2 & 1) ^ 1 == 2 + 0
tzr(2) == 1 ==> 0 + (2 & 1) ^ 1 == 0 + 1
tzr(1) == 0 ==> 0 + (1 & 1) ^ 1 == 0 + 0
Program ended with exit code: 0
You say, "I need a program that returns the number of trailing zeros in the binary rapresentation of a number." But does it have to be the program you found? Here's an alternative solution that implements tzr() in exactly one line of code,
#include <stdio.h>
#include <stdlib.h>
int tzr(int n) { /* --- every time n is even, add 1 and check n/2 --- */
return ( (n/2)*2 == n? 1+tzr(n/2) : 0 ); }
int main ( int argc, char *argv[] ) { /* --- test driver --- */
int n = (argc>1? atoi(argv[1]) : 1000);
printf("tzr(%d) = %d\n", n,tzr(n)); }
Is that any easier to understand?
(P.S. You could use bit masks and shifts instead of my divides and multiplies. That might be a little more efficient, but I thought my way might be a little more straightforward to read.)

Strange result with bitshift operations

I am trying to understand bishift operations better so I wrote myself a little program.
unsigned char a = 240;
a= (a << 3) >> 7;
printf("a: %u\n",a);
Now I would imagine that the result would be something like :
11110000 // 240
10000000 // << 3
00000001 // >> 7
So 1, but I get 15. I am confused... Any help is appreciated!
Your problem is that this statement : (a << 3) converts the input to an int . So at this point you have 240 * 2 ^ 3 = 1920
00000000000000000000011110000000
Then you are dividing the previous result by 2 ^ 7 = 128 so you have : 15
00000000000000000000000000001111
Which is exactly what you are getting as a result.
If you wanted to truncate bits you could have used :
printf("a: %u\n",a & 1); //get only last bit so you would have 1 as a result!
printf("a: %u\n",a & 255); //get all 8 bits
Hope this helped!
The expressions are evaluated as (unsigned) ints. (default int promotion). Casting(truncation) to a narrower type only happens just prior to the final assignment.
When you shifted, it casted a into an integer type larger than 8 bits, so the top 4 bits were saved
#include <stdio.h>
int main() {
unsigned char a = 240;
a = (a << 3);
a = (a >> 7);
printf("a: %u\n",a);
return 0;
}
prints 1
While shifting the types are automatically promoted to int which is wider than char (most often). So, it can store all your bits.
To get what you expect you would have to do
a = a << 3;
a = a >> 7;
or
a = ((unsigned char)(a << 3)) >> 7;

returns x with the n bits that begin at position p set to the rightmost n bits of y, leaving other bits unchanged

my solution
get the rightmost n bits of y
a = ~(~0 << n) & y
clean the n bits of x beginning from p
c = ( ~0 << p | ~(~0 << (p-n+1))) & x
set the cleaned n bits to the n rightmost bits of y
c | (a << (p-n+1))
it is rather long statements. do we have a better one?
i.e
x = 0 1 1 1 0 1 1 0 1 1 1 0
p = 4
y = 0 1 0 1 1 0 1 0 1 0
n = 3
the 3 rightmost bits of y is 0 1 0
it will replace x from bits 4 to bits 2 which is 1 1 1
I wrote similar one:
unsigned setbits (unsigned x, int p, int n, unsigned y)
{
return (x & ~(~(~0<<n)<<(p+1-n)))|((y & ~(~0<<n))<<(p+1-n));
}
There are two reasonable approaches.
One is yours: Grab the low n bits of y, nuke the middle n bits of x, and "or" them into place.
The other is to build the answer from three parts: Low bits "or" middle bits "or" high bits.
I think I actually like your version better, because I bet n and p are more likely to be compile-time constants than x and y. So your answer becomes two masking operations with constants and one "or"; I doubt you will do better.
I might modify it slightly to make it easier to read:
mask = (~0 << p | ~(~0 << (p-n+1)))
result = (mask & a) | (~mask & (y << (p-n+1)))
...but this is the same speed (indeed, code) as yours when mask is a constant, and quite possibly slower when mask is a variable.
Finally, make sure you have a good reason to worry about this in the first place. Clean code is good, but for something this short, put it in a well-documented function and it does not matter that much. Fast code is good, but do not attempt to micro-optimize something like this until your profiler tells you do. (Modern CPUs do this stuff very fast; it is unlikely your application's performance is bounded by this sort of function. At the very least it is "innocent until proven guilty".)
Have a look at the following descriptive code:
int setbitsKR(int x, int p, int n, int y){
int shiftingDistance = p - n + 1,
bitmask = (1 << n) - 1, // example, 11
digitsOfY = (y & bitmask) << shiftingDistance, // whatever
bitmaskShiftedToLeft = bitmask << shiftingDistance, // 001100
invertedBitmaskShiftedToLeft = ~bitmaskShiftedToLeft; // 110011
// erase those middle bits of x
x &= invertedBitmaskShiftedToLeft;
// add those bits from y into x
x |= digitsOfY;
return x;
}
In short, it creates a bitmask (string of 1s), shifts them to get to that middle position of x, nukes those bits of x by &ing with a string of 0s (inverted bitmask), and finally |s that position with the right digits of y.

Swap two bits with a single operation in C?

Let's say I have a byte with six unknown values:
???1?0??
and I want to swap bits 2 and 4 (without changing any of the ? values):
???0?1??
But how would I do this in one operation in C?
I'm performing this operation thousands of times per second on a microcontroller so performance is the top priority.
It would be fine to "toggle" these bits. Even though this is not the same as swapping the bits, toggling would work fine for my purposes.
Try:
x ^= 0x14;
That toggles both bits. It's a little bit unclear in question as you first mention swap and then give a toggle example. Anyway, to swap the bits:
x = precomputed_lookup [x];
where precomputed_lookup is a 256 byte array, could be the fastest way, it depends on the memory speed relative to the processor speed. Otherwise, it's:
x = (x & ~0x14) | ((x & 0x10) >> 2) | ((x & 0x04) << 2);
EDIT: Some more information about toggling bits.
When you xor (^) two integer values together, the xor is performed at the bit level, like this:
for each (bit in value 1 and value 2)
result bit = value 1 bit xor value 2 bit
so that bit 0 of the first value is xor'ed with bit 0 of the second value, bit 1 with bit 1 and so on. The xor operation doesn't affect the other bits in the value. In effect, it's a parallel bit xor on many bits.
Looking at the truth table for xor, you will see that xor'ing a bit with the value '1' effectively toggles the bit.
a b a^b
0 0 0
0 1 1
1 0 1
1 1 0
So, to toggle bits 1 and 3, write a binary number with a one where you want the bit to toggle and a zero where you want to leave the value unchanged:
00001010
convert to hex: 0x0a. You can toggle as many bits as you want:
0x39 = 00111001
will toggle bits 0, 3, 4 and 5
You cannot "swap" two bits (i.e. the bits change places, not value) in a single instruction using bit-fiddling.
The optimum approach if you want to really swap them is probably a lookup table. This holds true for many 'awkward' transformations.
BYTE lookup[256] = {/* left this to your imagination */};
for (/*all my data values */)
newValue = lookup[oldValue];
The following method is NOT a single C instruction, it's just another bit fiddling method. The method was simplified from Swapping individual bits with XOR.
As stated in Roddy's answer, a lookup table would be best. I only suggest this in case you didn't want to use one. This will indeed swap bits also, not just toggle (that is, whatever is in bit 2 will be in 4 and vice versa).
b: your original value - ???1?0?? for instance
x: just a temp
r: the result
x = ((b >> 2) ^ (b >> 4)) & 0x01
r = b ^ ((x << 2) | (x << 4))
Quick explanation: get the two bits you want to look at and XOR them, store the value to x. By shifting this value back to bits 2 and 4 (and OR'ing together) you get a mask that when XORed back with b will swap your two original bits. The table below shows all possible cases.
bit2: 0 1 0 1
bit4: 0 0 1 1
x : 0 1 1 0 <-- Low bit of x only in this case
r2 : 0 0 1 1
r4 : 0 1 0 1
I did not fully test this, but for the few cases I tried quickly it seemed to work.
This might not be optimized, but it should work:
unsigned char bit_swap(unsigned char n, unsigned char pos1, unsigned char pos2)
{
unsigned char mask1 = 0x01 << pos1;
unsigned char mask2 = 0x01 << pos2;
if ( !((n & mask1) != (n & mask2)) )
n ^= (mask1 | mask2);
return n;
}
The function below will swap bits 2 and 4. You can use this to precompute a lookup table, if necessary (so that swapping becomes a single operation):
unsigned char swap24(unsigned char bytein) {
unsigned char mask2 = ( bytein & 0x04 ) << 2;
unsigned char mask4 = ( bytein & 0x10 ) >> 2;
unsigned char mask = mask2 | mask4 ;
return ( bytein & 0xeb ) | mask;
}
I wrote each operation on a separate line to make it clearer.
void swap_bits(uint32_t& n, int a, int b) {
bool r = (n & (1 << a)) != 0;
bool s = (n & (1 << b)) != 0;
if(r != s) {
if(r) {
n |= (1 << b);
n &= ~(1 << a);
}
else {
n &= ~(1 << b);
n |= (1 << a);
}
}
}
n is the integer you want to be swapped in, a and b are the positions (indexes) of the bits you want to be swapped, counting from the less significant bit and starting from zero.
Using your example (n = ???1?0??), you'd call the function as follows:
swap_bits(n, 2, 4);
Rationale: you only need to swap the bits if they are different (that's why r != s). In this case, one of them is 1 and the other is 0. After that, just notice you want to do exactly one bit set operation and one bit clear operation.
Say your value is x i.e, x=???1?0??
The two bits can be toggled by this operation:
x = x ^ ((1<<2) | (1<<4));
#include<stdio.h>
void printb(char x) {
int i;
for(i =7;i>=0;i--)
printf("%d",(1 & (x >> i)));
printf("\n");
}
int swapb(char c, int p, int q) {
if( !((c & (1 << p)) >> p) ^ ((c & (1 << q)) >> q) )
printf("bits are not same will not be swaped\n");
else {
c = c ^ (1 << p);
c = c ^ (1 << q);
}
return c;
}
int main()
{
char c = 10;
printb(c);
c = swapb(c, 3, 1);
printb(c);
return 0;
}

Resources