How to add and extract bits to a byte? - c

I am trying to understand bit and byte manipulation and I have seen many examples in SO. Still, I have some questions regarding my understanding.
First, lets say we have a byte array with the byte order as Least Significant Byte. I want to get the byte 2 from this array. I can get the byte like byte[1]. Am I right?
Second, we have a byte array with the byte order as Least Significant Byte. And I want to get first 2 bits of the byte 1!. How can I get the first 2 bits from that byte?
Also, how can I add a number into the first 2 bits of a byte?
Any help or link to understand those logics are much appreciated.

First, lets say we have a byte array with the byte order as LSB. I want to get the byte 2 from this array. I can get the byte like byte[1]. Am I right?
Yes.
Second, we have a byte array with the byte order as LSB. And I want to get first 2 bits of the byte 1!. How can I get the first 2 bits from that byte? Also, how can I add a number into the first 2 bits of a byte?
You can use the bitwise AND operator & with the constant 3 to retrieve only the first two bits. By doing num & 3 it will realize a condition operation between each bit of num and 3 returning 1 as resultant bit only if both bits are 1. As 3 have only its 2 first bits set, every bit in num other than the first 2 will be ignored.
unsigned char foo = 47;
unsigned char twobits = foo & 3; // this will return only the value of the two bits of foo.
unsigned char number_to_add = 78;
twobits &= (number_to_add & 3); // this will get the values of the 2 bits of number_to_add_ and then assign it to the 2 bits of variable twobits.
Or if you don't care of the endianess you can use bitfields:
struct st_foo
{
unsigned char bit1 : 1;
unsigned char bit2 : 1;
unsigned char the_rest : 6;
};
struct st_foo my_byte;
my_byte.bit1 = 1;
my_byte.bit2 = 0;

Related

How to analyze bytes of a variable's value in C

is it possible to divide for example an integer in n bits?
For example, since an int variable has a size of 32 bits (4 bytes) is it possible to divide the number in 4 "pieces" of 8 bits and put them in 4 other variables that have a size of 8 bits?
I solved using unsigned char *pointer pointing to the variable that I want to analyze bytes, something like this:
int x = 10;
unsigned char *p = (unsigned char *) &x;
//Since my cpu is little endian I'll print bytes from the end
for(int i = sizeof(int) - 1; i >= 0; i--)
//print hexadecimal bytes
printf("%.2x ", p[i]);
Yes, of course it is. But generally we just use bit operations directly on the bits (called bitops) using bitwise operators defined for all discrete integer types.
For instance, if you need to test the 5th least significant bit you can use x &= 1 << 4 to have x just to have the 5th bit set, and all others set to zero. Then you can use if (x) to test if it has been set; C doesn't use a boolean type but assumes that zero is false and any other value means true. If you store 1 << 4 into a constant then you have created a "(bit) mask" for that particular bit.
If you need a value 0 or 1 then you can use a shift the other way and use x = (x >> 4) & 1. This is all covered in most C books, so I'd implore you to read about these bit operations there.
There are many Q/A's here how to split integers into bytes, see e.g. here. In principle you can store those in a char, but if you may require integer operations then you can also split the int into multiple values. One problem with that is that an int is just defined to at least store values from -32768 to 32767. That means that the number of bytes in an int can be 2 bytes or more.
In principle it is also possible to use bit fields but I'd be hesitant to use those. With an int you will at least know that the bits will be stored in the least significant bits.

How to handle a bunch of 0s and 1s with a microcontroller?

I'm making a program to receive a bunch of 0's and 1's with a µC and need to take any amount of bits (1 to 16) from any position.
I.E. I have 150 bits and I want to take 6 bits from the 32th bit and copy it to a char (8bits) variable; I know I can do it with strings by saving as ASCII 0's and 1's, but I have not a lot of RAM, so I need to save it as bits.
The bigger variable is a unsigned 32 bits long, but save the data is not my problem, the problem is how to access to a specific bits positions and copy that to a char(8) variable.
You can use bitwise operators:
//bits: your bits (byte array), start: index of the first bit of the char you want
char select(char* bits, int start) {
dec = start%8;
return bits[start/8]>>dec + bits[start/8+1]<<dec;
}
The code above supposed start < (bits.size()-8)
[EDIT]
You can change the char* to any type you want. However you will need to change dec value to the appropriate number of bits (8*SIZE_IN_BYTES) and then apply operator | ("logical or") to get your char back
example:
char select(int* bits, int start) {
nbitsint = 8*4;
dec = start%nbitsint;
if (dec < nbitsint-8) {
// | 0xff creates creates a byte
return (bits[start/nbitsint]>>((3-dec/8)*8+dec%8) | 0xff;
}
// Getting a byte which is astride two values is tricky
return (bits[start/nbitsint]>>(start%8) + bits[start/nbitsint+1]<<(start%8) | 0xff;
}

Read a single bit from a buffer of char

I would to implement a function like this:
int read_single_bit(unsigned char* buffer, unsigned int index)
where index is the offset of the bit that I would want to read.
How do I use bit shifting or masking to achieve this?
You might want to split this into three separate tasks:
Determining which char contains the bit that you're looking for.
Determining the bit offset into that char that you need to read.
Actually selecting that bit out of that char.
I'll leave parts (1) and (2) as exercises, since they're not too bad. For part (3), one trick you might find useful would be to do a bitwise AND between the byte in question and a byte with a single 1 bit at the index that you want. For example, suppose you want to get the fourth bit out of a byte. You could then do something like this:
Byte: 11011100
Mask: 00001000
----------------
AND: 00001000
So think about the following: how would you generate the mask that you need given that you know the bit index? And how would you convert the AND result back to a single bit?
Good luck!
buffer[index/8] & (1u<<(index%8))
should do it (that is, view buffer as a bit array and test the bit at index).
Similarly:
buffer[index/8] |= (1u<<(index%8))
should set the index-th bit.
Or you could store a table of the eight shift states of 1 and & against that
unsigned char bits[] = { 1u<<0, 1u<<1, 1u<<2, 1u<<3, 1u<<4, 1u<<5, 1u<<6, 1u<<7 };
If your compiler doesn't optimize those / and % to bit ops (more efficient), then:
unsigned_int / 8 == unsigned_int >> 3
unsigned_int % 8 == unsigned_int & 0x07 //0x07 == 0000 0111
so
buffer[index>>3] & (1u<<(index&0x07u)) //test
buffer[index>>3] |= (1u<<(index&0x07u)) //set
One possible implementation of your function might look like this:
int read_single_bit(unsigned char* buffer, unsigned int index)
{
unsigned char c = buffer[index / 8]; //getting the byte which contains the bit
unsigned int bit_position = index % 8; //getting the position of that bit within the byte
return ((c >> (7 - bit_position)) & 1);
//shifting that byte to the right with (7 - bit_position) will move the bit whose value you want to know at "the end" of the byte.
//then, by doing bitwise AND with the new byte and 1 (whose binary representation is 00000001) will yield 1 or 0, depending on the value of the bit you need.
}

How to store two different things in one byte and then access them again?

I am trying to learn C for my class. One thing I need to know is given an array, I have to take information from two characters and store it in one bytes. For eg. if string is "A1B3C5" then I have to store A = 001 in higher 3bits and then store 1 in lower 5bits. I have to function that can get two chars from array at a time and print it here is that function,
void print2(char string[])
{
int i = 0;
int length = 0;
char char1, char2;
length = strlen(string);
for ( i = 0; i <length; i= i + 2)
{
char1 = string[i];
char2 = string[i+1];
printf("%c, %c\n", char1, char2);
}
}
but now i am not sure how to get it encoded and then decode again. Can anyone help me please?
Assuming an ASCII character set, subtract '#' from the letter and shift left five bits, then subtract '0' from the character representing the digit and add it to the first part.
So you've got a byte, and you want the following bit layout:
76543210
AAABBBBB
To store A, you would do:
unsigned char result;
int input_a = somevalue;
result &= 0x1F; // Clear the upper 3 bits.
// Store "A": make sure only the lower 3 bits of input_a are used,
// Then shift it by 5 positions. Finally, store it by OR'ing.
result |= (char)((input_a & 7) << 5);
To read it:
// Simply shift the byte by five positions.
int output_a = (result >> 5);
To store B, you would do:
int input_b = yetanothervalue;
result &= 0xE0; // Clear the lower 5 bits.
// Store "B": make sure only the lower 5 bits of input_b are used,
// then store them by OR'ing.
result |= (char)(input_b & 0x1F);
To read it:
// Simply get the lower 5 bits.
int output_b = (result & 0x1F);
You may want to read about the boolean operations AND and OR, bit shifting and finally bit masks.
First of all, one bit can only represent two states: 0 and 1, or TRUE and FALSE. What you mean is a Byte, which consists of 8 bits and can thus represent 2^8 states.
Two put two values in one byte, use logical OR (|) and bitwise shift (<< and >>).
I don't post the code here since you should learn this stuff - it's really important to know what bits and bytes are and how to work with them. But feel free to ask follow up question if something is not clear to you.

how to retrieve 1 bit from byte array(unsigned char array) in C

I have to retrieve first bit from 1 byte.
For this i stored whole 1 byte in unsigned char Array. Now i retrieved first bit as per below code:
unsigned char byteArray[100];
.....
.....//some code to store 1 byte in byte array
//now 1st bit will be:
int bit=(int) byteArray[0];
I just wanted to confirm that step involved in retrieving 1st bit is right or not? Is there any better way to retrieve single bit from unsigned char array(byte array) in C.
How (and why) do you store a byte in a byte array for this purpose? Its not necessary.
In any case, if you want to retrieve the first bit of a byte, all you have to do is one bit operation.
unsigned char byte = <some random value>; // your byte containing the value.
unsigned int first_bit = byte & 1; // for Least significant bit
The operation byte & 1 is a bitwise AND operation.
No, the array indexer is going to return data the size of an unsigned char, not a single bit. Use byteArray[0] & 1; - masking the value so that you only get the first bit (depending on which end is the "first"). The other end would be & 128.

Resources