Using Bitwise Operators to get Bit Values in C - c

I am writing a program in C where I am comparing two bytes of data, and then seeing if the bytes are different, and if so, at which bits.
This is what I have so far:
int var1 = 81; //Binary: 0101 0001
int var2 = 193; //Binary: 1100 0001
int diff = var1 ^ var2; //diff = 1001 0000 / 144
Basically I know how to use the XOR bitwise operator to see which bits are different between the two variables, but from here I don't know how to use diff to figure out which bits are the differences. For example, in my above code I'd want to use diff to output "Bit 5 and Bit 8 are different".

You can use a for loop to get that idea and make bitwise AND with 1 properly left shifted to get the set bits positions
for(size_t i = 0; i < sizeof(int)*8; i++){
if( diff & (1U << i))
printf("%zu is different\n",i+1);
}

Far easier to start with unsigned types when doing bit manipulations.
As #coderredoc inquired about solutions across various platforms, even uncommon ones:
Using int:
When int diff is negative, conversion to an unsigned (via masking with an unsigned) may change its bit pattern.
An int may have more than 8 bits per "byte". Diminishes correctness of sizeof(int)*8.
Various integer types may have padding (rare). Diminishes correctness of sizeof(int)*CHAR_BIT.
// OP wants to report first bit index as 1. 0 is more common.
#define BIT_REPORT_OFFSET 0
int bit_position = 0;
int mask;
do {
mask = 1 << bit_position;
if (diff & mask) {
printf("Bit %d\n", bit_position + BIT_REPORT_OFFSET);
}
bit_position++;
} while (mask < INT_MAX/2);
if (diff < 0) {
printf("Bit %d\n", bit_position + BIT_REPORT_OFFSET);
}
For maximum portability, avoid changing types, changing the value of diff and use constants from <limits.h> rather than compute them.

use unsigned int instead of int; then you can use
for (unsigned int pos = 0; diff; ++pos) {
if (diff & 1)
printf("difference in pos %u\n", pos);
diff >>= 1;
}
or
while (diff) {
int pos = ffs(diff);
printf("difference in pos %d\n", pos);
diff &= ~(1u << pos);
}

To get the different bits position, lets say you have 4 byte integer
for(int bit_index = sizeof(diff) - 1; bit_index >= 0;bit_index-- ) {
if((diff >> bit_index & 1) == 1 ){ /* if particular bit is 1, that bit_index value you can use */
printf("[%d] bit is different or 1 \n",bit_index);
}

Related

How to use signed or unsigned integer for bit mapping in C?

I want to reset the 31st bit (last bit, 0 to 31 range) of int32_t, only this case seems to fail.
i.e., Output failed for the case when 'i' is 31, it's returning -1. What is the error and how do I resolve this?
#include <stdio.h>
#include <stdlib.h>
void Release(int ResetBit, int32_t *Val)
{
int32_t testBit = 1; /* XoR Bit */
if (ResetBit >= 0 && ResetBit < 32)
{
testBit = (testBit << ResetBit);
*Val ^= testBit;
}
else
{
perror("Max range is 0-31 only, failed! ");
//exit(1);
}
}
int main(int argc, char const *argv[])
{
int count = 0;
for (int i = 0; i < 32; i++)
{
int32_t MaxValue = 2147483647;
Release(i, &MaxValue);
printf("MaxValue = %d NodeID = % d\n", MaxValue, i);
count++;
}
printf("%d", count);
return 0;
}
Output for the case i = 31 is:
MaxValue = -1 NodeID = 31
First of all: Don't use signed integers for bitmaps. Always use unsigned. The reason for that is that bit shifting on signed integers may result in undefined behavior while shifting unsigned integers are always safe.
Secondly: You are using XOR in the Release function. XOR with testBit will not clear a bit. XOR will toggle the bit value, i.e. 1 becomes 0 and 0 becomes 1. Instead you want: *Val &= ~testBit; It works like:
If testBit is 0000.0000.0000.0000.0000.0000.0000.1000
then ~testbit is 1111.1111.1111.1111.1111.1111.1111.0111
then *Val &= ... will clear bit number 3 and keep all other unchanged
as `&` is a bitwise AND operation.
When using unsigned remember to change the printf to print an unsigned instead of using %d, i.e. like printf("%" PRIu32 "\n", uint32t_variable);.
EDIT
What went wrong with the XOR?
Let's assume that you are using uint32_t and XOR, then this will happen:
Your input is
0111.1111.1111.1111.1111.1111.1111.1111
and you XOR with
1000.0000.0000.0000.0000.0000.0000.0000
which toggles bit 31 resulting in
1111.1111.1111.1111.1111.1111.1111.1111
The function was supposed to clear bit 31 but it didn't. XOR is just not the correct operator for that.
If you don't need an actual signed type, use uint32_t and all problems will go away. The problem with using bitwise operators on signed types is various forms of poorly-defined behavior.
For example, left-shifting something into the sign bit of a int32_t leads to undefined behavior, meaning a potential bug in case your compiler doesn't cover that case with a non-standard extension. Similarly, right-shifting a negative number can either lead to arithmetic or logic shift, the C standard doesn't specify which one, but allows both forms.
That being said, if you simply wish to set/clear bit 31 of an int32_t, it's well-defined to do so like this:
int32_t i32 = ...;
i32 |= 1u << 31; // set MSB
i32 &= ~(1u << 31); // clear MSB
i32 ^= 1u << 31; // toggle MSB
Where the u is ensuring unsigned arithmetic.
Use the correct bitwise operation. to reset bit use &
int32_t ResetBit(int bit, int32_t *val)
{
uint32_t mask = ~(1UL << bit);
*val &= mask;
return *val;
}
and usage:
void printnitd(int32_t val)
{
for(uint32_t mask = 1UL << 31; mask; mask >>= 1)
{
printf("%c", (val & mask) ? '1' : '0');
}
}
int main(void)
{
for(int bit = 0; bit < 32; bit++)
{
int32_t a = -1;
printf("bit %u = ", a);
printnitd(ResetBit(bit, &a));
printf("\n");
}
}

Effective bits calculation along the array in specified position on STM32

I'm wondering if someone know effective approach to calculate bits in specified position along array?
Assuming that OP wants to count active bits
size_t countbits(uint8_t *array, int pos, size_t size)
{
uint8_t mask = 1 << pos;
uint32_t result = 0;
while(size--)
{
result += *array++ & mask;
}
return result >> pos;
}
You can just loop the array values and test for the bits with a bitwise and operator, like so:
int arr[] = {1,2,3,4,5};
// 1 - 001
// 2 - 010
// 3 - 011
// 4 - 100
// 5 - 101
int i, bitcount = 0;
for (i = 0; i < 5; ++i){
if (arr[i] & (1 << 2)){ //testing and counting the 3rd bit
bitcount++;
}
}
printf("%d", bitcount); //2
Note that i opted for 1 << 2 which tests for the 3rd bit from the right or the third least significant bit just to be easier to show. Now bitCount would now hold 2 which are the number of 3rd bits set to 1.
Take a look at the result in Ideone
In your case you would need to check for the 5th bit which can be represented as:
1 << 4
0x10000
16
And the 8th bit:
1 << 7
0x10000000
256
So adjusting this to your bits would give you:
int i, bitcount8 = 0, bitcount5 = 0;
for (i = 0; i < your_array_size_here; ++i){
if (arr[i] & 0x10000000){
bitcount8++;
}
if (arr[i] & 0x10000){
bitcount5++;
}
}
If you need to count many of them, then this solution isn't great and you'd be better off creating an array of bit counts, and calculating them with another for loop:
int i, j, bitcounts[8] = {0};
for (i = 0; i < your_array_size_here; ++i){
for (j = 0; j < 8; ++j){
//j will be catching each bit with the increasing shift lefts
if (arr[i] & (1 << j)){
bitcounts[j]++;
}
}
}
And in this case you would access the bit counts by their index:
printf("%d", bitcounts[2]); //2
Check this solution in Ideone as well
Let the bit position difference (e.g. 7 - 4 in this case) be diff.
If 2diff > n, then code can add both bits at the same time.
void count(const uint8_t *Array, size_t n, int *bit7sum, int *bit4sum) {
unsigned sum = 0;
unsigned mask = 0x90;
while (n > 0) {
n--;
sum += Array[n] & mask;
}
*bit7sum = sum >> 7;
*bit4sum = (sum >> 4) & 0x07;
}
If the processor has a fast multiply and n is still not too large, like n < pow(2,14) in this case. (Or n < pow(2,8) in the general case)
void count2(const uint8_t *Array, size_t n, int *bit7sum, int *bit4sum) {
// assume 32 bit or wider unsigned
unsigned sum = 0;
unsigned mask1 = 0x90;
unsigned m = 1 + (1u << 11); // to move bit 7 to the bit 18 place
unsigned mask2 = (1u << 18) | (1u << 4);
while (n > 0) {
n--;
sum += ((Array[n] & mask1)*m) & mask2;
}
*bit7sum = sum >> 18;
*bit4sum = ((1u << 18) - 1) & sum) >> 4);
}
Algorithm: code is using a mask, multiply, mask to separate the 2 bits. The lower bit remains in it low position while the upper bit is shifted to the upper bits. Then a parallel add occurs.
The loop avoids any branching aside from the loop itself. This can make for fast code. YMMV.
With even larger n, break it down into multiple calls to count2()

XORing a 32 bit integer with itself

I'm stuck on XORing a 32-bit integer with it itself. I'm supposed to XOR the 4 8-bit portions of the integers. I understand how it works, but without storing the integer anywhere, I don't get how to do this.
I've thought it over and I'm thinking of using binary left shift and right shift operators to separate the 32 bit integer into 4 parts to XOR them. For example, if I were to use an 8-bit integer, I would do something like this:
int a = <some integer here>
(a << 4) ^ (a >> 4)
So far, it isn't working the way I thought it would work.
Here's a part of my code:
else if (choice == 2) {
int bits = 8;
printf("Enter an integer for checksum calculation: ");
scanf("%d", &in);
printf("Integer: %d, ", in);
int x = in, i;
int mask = 1 << sizeof(int) * bits - 1;
printf("Bit representation: ");
for (i = 1; i <= sizeof(int) * bits; i++) {
if (x & mask)
putchar('1');
else
putchar('0');
x <<= 1;
if (! (i % 8)) {
putchar(' ');
}
}
printf("\n");
}
Here's an example of an output:
What type of display do you want?
Enter 1 for character parity, 2 for integer checksum: 2
Enter an integer for checksum calculation: 1024
Integer: 1024, Bit representation: 00000000 00000000 00000100 00000000
Checksum of the number is: 4, Bit representation: 00000100
To accumulate the XOR of 8-bit values, you simply shift and XOR each part of the value. Conceptually it's this:
uint32_t checksum = ( (a >> 24) ^ (a >> 16) ^ (a >> 8) ^ a ) & 0xff;
However, since XOR can be done in any order, you can do the same with fewer operations:
uint32_t checksum = (a >> 16) ^ a;
checksum = ((checksum >> 8) ^ checksum) & 0xff;
If you're doing this over many values, you can extend this idea by only condensing the value at the very end. This is quite similar to how parallel commutative operations are done in larger registers with technologies like SIMD (and indeed, compilers with SIMD support should be able to optimize the following code to make it much faster):
uint32_t simple_checksum( uint32_t *v, size_t count )
{
uint32_t checksum = 0;
uint32_t *end = v + count;
for( ; v != end; v++ )
{
checksum ^= *v; /* accumulate XOR of each 32-bit value */
}
checksum ^= (checksum >> 16); /* XOR high and low words into low word */
checksum ^= (checksum >> 8 ); /* XOR each byte of low word into low byte */
return checksum & 0xff; /* everything from bits 8-31 is rubbish */
}
In general Xoring a number with itself should provide you with the value 0 so you can just as easily set the variable to 0.
0100101^0100101=0
This is a result of the Karnaugh map for the xor operation providing a 0 when both bits are a one, or both are a zero.

Understanding bit manipulation (set/clear) in C programming

I'm stuck understanding bit operations on integers in C.
Suppose I have the number 13. Its binary representation is 1101. How can I set the bit at its second position? How can I clear the bit?
Here is the function I wrote so far for setting the bit:
int setBit(int data, int pos, int val)
{
if (val==1)
data |= (1U << (pos - 1));
else
data ^= (1U << (pos-1));
return data;
}
Will this work correctly?
n = n & (~(1U <<x)) will reset the bit in position x.
Actually what we are doing suppose n=1101
We want to reset 3rd bit.
How does it work?
So 1U <<3=000....1000
~( 1U <<3)=111....0111
n=000..1101
& 111..0111
Result is 000..0101.
For inserting a bit y at position x:(position starts from 0)
1101---->11y01
Giving the example for position 2.
num= FFFF FFFF (in hex)(all 1's) //1111......1111
number=N // in which you will insert bit
num1=num<<x; //for x=2 as in this case
//num1=1111.....1100
num2=~(num1); //num2=0000.....0011
lowbits=N & num2; // =0000.....0001 (N=1101)
highbits= N &num1;// =0000.....1100
highbits<<=1; // =0000....11000
N= highbits | lowbits;//=0000....11001
Now set the x-th bit(here x=2) as you required using the method described below
Note: More generally changing the kth bit of number n to y (maybe 0 or 1) can be done this way
n^=(-y ^ n) & (1U <<k); (&- logical and)
Deletion of a bit is similar to insertion. Step by step perform the operation and you will get it.
EDIT: I have changed the use of 1 to 1U because in first case when using only 1 without any modifiers is defined to be an signed int. From K&R the right shifts of signed values are implementation defined. Also if you left-shift a signed number so that the sign bit is affected, the result is undefined.
These operations on unsigned value have well define behaviour: Vacated fields are filled with zeroes.
Setting, clearing and toggling the state of a bit is straightforward:
inline void bit_set (unsigned long *bf, unsigned char n)
{ *bf |= (1 << n); }
inline void bit_clear (unsigned long *bf, unsigned char n)
{ *bf &= ~(1 << n); }
inline void bit_toggle (unsigned long *bf, unsigned char n)
{ *bf ^= (1 << n); }
Note: bitfields, and the functions above, are zero based (i.e. the least significant bit is bit 0 not bit 1) So if you want to clear, set or toggle the second bit from the right (bit index 1, the 2's bit (binary), or bit 2 counting right-to-left), you pass a bit index of 1. n in the functions above is the bit index. The following is a quick reference:
+-----+-----+-----+-----+-----+-----+-----+-----+
bit index | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+-----+-----+-----+-----+-----+-----+-----+-----+
binary | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
+-----+-----+-----+-----+-----+-----+-----+-----+
Here is a quick example of the use operating on bit 1, (the 2's bit in binary):
#include <stdio.h>
#include <stdlib.h>
#define WDSZ 64
/* bit functions */
inline void bit_set (unsigned long *bf, unsigned char n) { *bf |= (1 << n); }
inline void bit_clear (unsigned long *bf, unsigned char n) { *bf &= ~(1 << n); }
inline void bit_toggle (unsigned long *bf, unsigned char n) { *bf ^= (1 << n); }
/* simple return of binary string */
char *binstr (unsigned long n);
int main (int argc, char **argv) {
unsigned long bf = (argc > 1) ? strtoul (argv[1], NULL, 10) : 13;
printf ("\n original value : %3lu (%s)\n", bf, binstr (bf));
bit_set (&bf, 1);
printf (" set bit 1 : %3lu (%s)\n", bf, binstr (bf));
bit_clear (&bf, 1);
printf (" clear bit 1 : %3lu (%s)\n", bf, binstr (bf));
bit_toggle (&bf, 1);
printf (" toggle bit 1 : %3lu (%s)\n\n", bf, binstr (bf));
return 0;
}
/* simple return of binary string */
char *binstr (unsigned long n) {
static char s[WDSZ + 1] = {0};
char *p = s + WDSZ;
while (n) {
p--;
*p = (n & 1) ? '1' : '0';
n >>= 1;
}
return p;
}
Output
$ ./bin/bitsetcleartoggle
original value : 13 (1101)
set bit 1 : 15 (1111)
clear bit 1 : 13 (1101)
toggle bit 1 : 15 (1111)
Here is a simple answer for what I understand your problem to be:
int setBit(int data, int pos, int val) {
if (val)
return data | (1U << (pos - 1));
else
return data & ~(1U << (pos - 1));
}
But I think numbering the bits starting at 1 is not a good idea. The more common usage is to number the bits from 0 to sizeof(type) * CHAR_BIT - 1
whenever I have a problem like this I will break it down into smaller parts...
suppose i have no 13 binary of 13 is 1101
now how can i add extra bit at second position?
ok that is pretty straight forward... first let make a number with a bit in the second position, zero's everywhere else... we will use an int for convenience...
int mask = 2; // or 0x2 if you rather or 0b10 if your compiler supports that ...
well that isn't very special, I can't reuse that machinery as it were... so let try a different way...
int mask = 1 << 1; // 1 in the fist position moved one to the left...
ok now we have part, now there are 2 intuitive ways to set that on our 13...
int answer = 13 | mask; // binary OR
or
int answer = 13 + mask;
these 2 are the same for 13... but will give you different answers for 14... because + always adds the value, and | will only change the bits that aren't set on the left side... so you need to pick the semantics that are correct for you...
now your second question is a little trickier ... first we will pick the same mask...
//pick nth bit
int mask = 1 < n;
// now to toggle that on a number... XOR
int answer = q ^ mask;
I like using the n'th vs position because it makes more sense in the 0 case...
//For Inserting Bit
int insertbit(int data,int pos,int val)
{
int no1,no2;
no1=data;
no1=no1>>(pos-1);
no1=no1<<(pos-1);
no2=data-no1;
no1=no1<<1;
no1=no1 | no2;
if(val==1)
{
no1=setbit(no1,pos,val);
}
return no1;
}
//Setting Bits
int setbit(int data,int pos,int val)
{
int no=1;
no=no<<(pos-1);
if(val==0)
{
no=~no;
data=data&no;
}
else
{
data=no|data;
}
return data;
}
I Coded This Way But I Need Some Shortcut for code insert function

What's up with this reversing bit order function?

I'm rather ashamed to admit that I don't know as much about bits and bit manipulation as I probably should. I tried to fix that this weekend by writing some 'reverse the order of bits' and 'count the ON bits' functions. I took an example from here but when I implemented it as below, I found I had to be looping while < 29. If I loop while < 32 (as in the example) Then when I try to print the integer (using a printBits function i've written) I seem to be missing the first 3 bits. This makes no sense to me, can someone help me out?
Thanks for everyone's help, I've added comments to show changes I've made.
int reverse(int n)
{
int r = 0;
int i = 0;
for(i = 0; i < 29; i++) //Should be i < 32
{
r = (r << 1) + (n & 1); //| instead of + to make it obvious I'm handling bits
n >>=1;
}
return r;
}
Here is my printBits function:
void printBits(int n)
{
int mask = 0X10000000; //unsigned int mask = 0X80000000;
while (mask)
{
if (mask & n)
{
printf("1");
}
else
{
printf("0");
}
mask >>= 1;
}
printf("\n");
}
And a working? reverse function
int reverse2(int n)
{
int r = n;
int s = sizeof(n) * 7; // int s = (sizeof(n) * 8) -1
for (n >>= 1; n; n >>=1)
{
r <<=1;
r |= n & 1;
s--;
r <<= s;
return r;
}
int mask = 0X10000000;
puts a 1 in bit 28. You want 0X80000000.
You have:
int mask = 0x10000000;
There are two problems here. You don't have the high bit set, and if you did, it still (probably) wouldn't work, as your compiler would be using arithmetic shift on a signed int.
You want to change your mask to:
unsigned int mask = 0x80000000;
For arithmetic shift, shifting 0x80000000 right will never become zero, as the sign bit will be magically extended into the other bits. See here for more details on arithmetic shift.
Print Bits is wrong, its 0x80000000 not 0x10000000.
>>> bin (0x80000000)
'0b10000000000000000000000000000000'
>>> bin (0x10000000)
'0b10000000000000000000000000000'
See 0x1... doesnt set the highest bit.
Instead of +, you should use | (bitwise or). And you should use < 32.
As written, this will reverse the lower 29 bits of n into r. The top three bits of n will be left in n (shifted down 29 bits) and not returned.
I would suspect a problem with your printBits function if you see something else.
edit
Your printBits function prints the lower 29 bits of n, so it all makes sense.

Resources