Bit extracting in embedded c - c

I am working on bit extracting from given byte.I have 32-bit 0XFA73DECB in binary 1111 1010 0111 0011 1101 1110 1100 1011.Now how to extract bit no. 7 to 22? Any one help me?

The following code first extracts the bits into another int and then outputs in binary.
#include <stdio.h>
#include <stdlib.h>
unsigned int a = 0xfa73decb;
int main()
{
unsigned int Bits = 0b00000011111111111111110000000000;
unsigned int Extract = (a & Bits) >> 10;
char Bin[20];
_itoa(Extract, Bin, 2);
printf("%s\n", Bin);
while (1);
}
The _itoa (the underline is because I'm using Visual Studio and the typical itoa is deprecated) means transform the integer Extract into a string with the radix of 2 and store it into the string Bin

To dynamically reading the inputs to extract the bits,
#include <stdio.h>
#include <stdlib.h>
unsigned int a = 0xfa73decb;
int main()
{
int msb;
int lsb;
unsigned int Extract;
printf("size of unsigned int = %d\n", sizeof(unsigned int)); // sizeof int : 4 bytes (32 bits)
scanf("%d", &lsb); // as per your requirement: 10
scanf("%d", &msb); // as per your requirement: 26
msb = (8*sizeof(unsigned int)) - msb; // msb = 32 - 26 ; // 6
lsb = lsb + msb ; // lsb = 10 + 6 ; // 16
Extract = (a << msb); // shifting 6 times left
printf("After Left shift = 0x%0x\n", Extract);
Extract = Extract >> lsb; // shifting 16 times right
printf("After Right shift = 0x%0x\n", Extract);
}
Input:
10 26
Output:
size of unsigned int = 4
After Left shift = 0x9cf7b2c0
After Right shift = 0x9cf7

Related

Creating duplicate bytes from a given function

So I have the below code which shifts a 32 bit int 6 bits to the left (s->data) then appends the last 6 bits of the int operand to the int s->data. I would like to use this code to create a function which takes an unsigned char x and copies x into the first 3 bytes of the int s->data leaving the final byte as 0. So for example, if we had x = 255 then s->data , in binary form, would be 11111111 11111111 11111111 000000000. Does anyone know how this can be achieved using the below code (dataCommand). So If i can only shift left by 6 bits and append 6 bits to the end of s->data, how can I get something of the form above?.
I know how to get say 255 from using s->data (we do dataCommand(128+64+(255/64))) followed by dataCommand(128+64+(255%64)). This is assuming s->data is 0 to begin with. So this would give 00000000 00000000 00000000 11111111. However , I would like something of the form 11111111 11111111 11111111 00000000.
I am really lost as to how to do this, so any help would be greatly appreciated. Below is the dataCommand function. Thank you. As always, it can be assumed s->data is 0 to begin with.
void dataCommand(int operand, state *s) {
printf("DATA BEFORE IS %x\n", s->data);
// shifts bits of current data fields six positions to left
s->data = s->data << 6;
// (operand & 63) masks 6 bits off the operand
// then we combine 6 bits of data with 6 bits of operand
s->data = (s->data | (operand & 63));
printf("DATA AFTER %x\n", s->data);
}
Comments in MyFunction below explain how to do this.
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
typedef struct state { int x, y, tx, ty; unsigned char tool; unsigned int start, data; bool end;} state;
void dataCommand(int operand, state *s) {
printf("DATA BEFORE IS %x\n", s->data);
// shifts bits of current data fields six positions to left
s->data = s->data << 6;
// (operand & 63) masks 6 bits off the operand
// then we combine 6 bits of data with 6 bits of operand
s->data = (s->data | (operand & 63));
printf("DATA AFTER %x\n", s->data);
}
void MyFunction(unsigned char x, state *s)
{
/* Create the target pattern that contains 0 in byte 0 and x in bytes 1,
2, and 3.
*/
uint32_t p = 0x01010100u * x;
/* For each six bits in p, or fragment thereof, in order from high bits to
low bits, shift those six bits down to the low six bits and give that
to dataCommand to insert into s->data.
*/
dataCommand(p >> 6*5, s);
dataCommand(p >> 6*4, s);
dataCommand(p >> 6*3, s);
dataCommand(p >> 6*2, s);
dataCommand(p >> 6*1, s);
dataCommand(p >> 6*0, s);
}
int main(void)
{
state s;
MyFunction(0x45, &s);
printf("data = 0x%08x.\n", s.data);
}

how do i split an unsigned 64 bit int into individual 8 bits? (little endian) in C

for example i have uint64_t value = 42 and i would like to split it into 8 uint8_t (8 bits), little endian. But I am unsure how to do the bit shifting. Help would be much appreciated.
If you want the individual bytes of a 64-bit value in little endian, then you can do the following:
In order to get the 1st byte, you simply apply the AND-bitmask 0xFF. This will mask out all bits except for the 8 least-significant bits.
In order to get the 2nd byte, you shift right by 8 bits before applying the bit-mask.
In order to get the 3rd byte, you shift right by 16 bits before applying the bit-mask.
In order to get the 4th byte, you shift right by 24 bits before applying the bit-mask.
(...)
In order to get the 8th byte, you shift right by 56 bits before applying the bit-mask.
Here is the code for the value 42 (which is the example in the question):
#include <stdio.h>
#include <stdint.h>
int main( void )
{
uint64_t value = 42;
uint8_t bytes[8];
//extract the individual bytes
for ( int i = 0; i < 8; i++ )
{
bytes[i] = value >> (8 * i) & 0xFF;
}
//print the individual bytes
for ( int i = 0; i < 8; i++ )
{
printf( "%2d ", bytes[i] );
}
printf( "\n" );
}
Output:
42 0 0 0 0 0 0 0
If you replace the value 42 with the value 74579834759 in the program above, then you get the following output:
135 247 77 93 17 0 0 0
The following code works on both little-endian and big-endian platforms. On both types of platforms, it will produce the bytes in little-endian byte order.
uint64_t input = 42;
uint8_t values[8];
values[0] = input >> 0 & 0xFF;
values[1] = input >> 8 & 0xFF;
values[2] = input >> 16 & 0xFF;
values[3] = input >> 24 & 0xFF;
values[4] = input >> 32 & 0xFF;
values[5] = input >> 40 & 0xFF;
values[6] = input >> 48 & 0xFF;
values[7] = input >> 56 & 0xFF;
Note that the & 0xFF is redundant here, but it makes the code more clear and it's useful if you want to do anything with the value other than immediately assign it to a uint8_t variable.
Macro extracts bth byte form the u integer
#define EXTRACT(u,b) ((u) >> (8 * (b)))
int foo(uint64_t x)
{
uint8_t b[8] = {
EXTRACT(x,0),
EXTRACT(x,1),
EXTRACT(x,2),
EXTRACT(x,3),
EXTRACT(x,4),
EXTRACT(x,5),
EXTRACT(x,6),
EXTRACT(x,7),
};
}
If the platform is little endian you can also use memcpy
void foo(uint64_t x)
{
uint8_t b[8];
memcpy(b, &x, sizeof(b));
}
Here's a pointer approach to retrieve byte data from u64 data I usually use. Just share with you. But in this way, the user has to take care of the order.
#include <stdio.h>
#include <stdint.h>
void main(void)
{
int i;
uint64_t v = 0x123456789abcdef0;
uint8_t* ptrb;
ptrb = (uint8_t*)&v;
for (i = 0; i < 8; i++)
{
printf("%2x ", ptrb[i]);
}
printf("\n");
}
Below is the output with my sample code,
$ ./foo
f0 de bc 9a 78 56 34 12

Re-Indexing Bits Within a Char

I have an exercise where I have to encode and decode strings at the bit level that are given in by the command line.
The caveat for this is that I have to use a permutation mapping to re-order the bits.
Here's an Example:
The User Inputs The Character To Encode
H
The Binary for H is
01001000
However, that is the regular mapping of the 8 bits, through 0-7.
My program will have to permute the bits to whatever Mapping Patter I use.
For Example, If I use Mapping 64752031
The Bits for the Char 'H'
01001000
Turn To
01000001
When encoding the char, the 0th bit turns to the 6th bit, the 2nd bit turns to the 4th bit, the 3rd bit turns to the 7th bit, and so on. Whatever is based on for that mapping.
Is there a way that I can manipulate and change the order of bits based on the permutation map given?
Thank you.
If you need to process large strings, it is probably better to use a look-up table that will precompute the translation.
#include <stdio.h>
unsigned char perm[256]; // permutation table
unsigned mapping[8]={6,4,7,5,2,0,3,1};
// assumes 7 6 5 4 3 2 1 0
// => 6 4 7 5 2 0 3 1
void mkperm(unsigned char perm[256]) {
for (int i=0; i<256; i++)
perm[i]=0;
for (int i=0;i<256;i++) {
for (int j=7; j>=0; j--) {
int pos=mapping[7-j]; // at mapping[0] is the new position of bit 7
if (i & (1<<j)) // only considers set bits, the table is previously cleared
perm[i] |= (1<<pos) ;
}
}
}
int main() {
mkperm(perm);
printf("%.2x => %.2x\n",'H',perm['H']);
}
mkperm() computes the permutation table by scanning the successive bits of every char. If a bit is set in char i, we set at position i in the translation table a bit at one at a logical weight given by the mapping. Setting this one is done by oring the content of cell i with a 1 properly shifted.
Use bitwise operators.
Here's an example of how to move the second bit to the seventh bit:
x |= (x & 1<<1) << 6;
x &= ~(1<<1);
If my bit numbering bothers anybody, I'm sorry. This is just how I read binary numbers.
You can also put this into an inline function:
inline int bit_mode(int *x, int bit1, int bit2)
{
*x |= *x & (1<<(bit1-1)) << (bit2-1);
*x &= ~(1<<(bit1-1));
return *x;
}
int a;
bit_mode(&a, 2, 7);
Just shift the bits to proper positions. After some fun, I think I've got this:
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <limits.h>
#include <stdint.h>
/**
* A little helper function
* get the bit number 'as' from the byte 'in'
* and put that bit as the number 'num' in the output
*/
static inline
uint8_t map_get_bit_as(uint8_t in,
uint8_t num, uint8_t as)
{
return (!!(in & (1 << as))) << num;
}
uint8_t map(unsigned long mapping, uint8_t in)
{
// static_assert(CHAR_BIT == 8, "are you insane?");
const int bit0 = mapping / 10000000 % 10;
const int bit1 = mapping / 1000000 % 10;
const int bit2 = mapping / 100000 % 10;
const int bit3 = mapping / 10000 % 10;
const int bit4 = mapping / 1000 % 10;
const int bit5 = mapping / 100 % 10;
const int bit6 = mapping / 10 % 10;
const int bit7 = mapping / 1 % 10;
return
map_get_bit_as(in, 0, bit0) |
map_get_bit_as(in, 1, bit1) |
map_get_bit_as(in, 2, bit2) |
map_get_bit_as(in, 3, bit3) |
map_get_bit_as(in, 4, bit4) |
map_get_bit_as(in, 5, bit5) |
map_get_bit_as(in, 6, bit6) |
map_get_bit_as(in, 7, bit7);
}
int main() {
printf("%#02x %#02x\n\n", 'H', map(64752031, 'H'));
}
will output:
0x48 0x41
tested on repl.
If I have correctly understood the order of bits as you are counting them then the corresponding function can look the following way as it is shown in the demonstrative program.
#include <stdio.h>
#include <limits.h>
#include <stdint.h>
char encode( char c, uint32_t mask )
{
unsigned char result = '\0';
for ( size_t i = 0; i < 2 * sizeof( mask ) ; i++ )
{
uint32_t bit = ( ( ( uint32_t )1 << ( CHAR_BIT - 1 - ( mask & 0xf ) ) ) & c ) != 0;
result |= bit << i;
mask >>= 4;
}
return ( char )result;
}
int main( void )
{
uint32_t mask = 0x64752031;
char c = 'H';
printf( "c = %hhx\n", c );
c = encode( c, mask );
printf( "c = %hhx\n", c );
}
The program output is
c = 48
c = 41

Set first 10 bit of int

I have a 32-bit int and I want to set the first 10 bit to a specific number.
IE
The 32-bit int is:
11101010101010110101100100010010
I want the first 10 bit to be the number 123, which is
0001111011
So the result would be
00011110111010110101100100010010
Does anyone know the easiest way I would be able to do this? I know that we have to do bit-shifting but I'm not good at it so I'm not sure
Thank you!
uint32_t result = (input & 0x3fffff) | (newval << 22);
0x3fffff masks out the highest 10 bits (it has the lowest 22 bits set). You have to shift your new value for the highest 10 bits by 22 places.
Convert inputs to unsigned 32-bit integers
uint32_t num = strtoul("11101010101010110101100100010010", 0, 2);
uint32_t firstbits = 123;
Mask off the lower 32-10 bits. Create mask by shifting a unsigned long 1 22 places left making 100_0000_0000_0000_0000_0000 then decrementing to 11_1111_1111_1111_1111_1111
uint32_t mask = (1UL << (32-10)) - 1;
num &= mask;
Or in firstbits shifted left by 32-10
num |= firstbits << (32-10);
Or in 1 line:
(num & (1UL << (32-10)) - 1) | (firstbits*1UL << (32-10))
Detail about firstbits*1UL. The type of firstbits is not defined by OP and may only be a 16-bit int. To insure code can shift and form an answer that exceeds 16 bits (the minimum width of int), multiple by 1UL to insure the value is unsigned and has at least 32 bit width.
You can "erase" bits (set them to 0) by using a bit wise and ('&'); bits that are 0 in either value will be 0 in the result.
You can set bits to 1 by using a bit wise or ('|'); bits that are 1 in either value will be 1 in the result.
So: and your number with a value where the first 10 bits are 0 and the rest are 1; then 'or' it with the first 10 bits you want put in, and 0 for the other bits. If you need to calculate that value, then a left-shift would be the way to go.
You can also take a mask and replace approach where you zero the lower bits required to hold 123 and then simply | (OR) the value with 123 to gain the final result. You can accomplish the exact same thing with shifts as shown by several other answers, or you can accomplish it with masks:
#include <stdio.h>
#ifndef BITS_PER_LONG
#define BITS_PER_LONG 64
#endif
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
char *binpad2 (unsigned long n, size_t sz);
int main (void) {
unsigned x = 0b11101010101010110101100100010010;
unsigned mask = 0xffffff00; /* mask to zero lower 8 bits */
unsigned y = 123; /* value to replace zero bits */
unsigned masked = x & mask; /* zero the lower bits */
/* show intermediate results */
printf ("\n x : %s\n", binpad2 (x, sizeof x * CHAR_BIT));
printf ("\n & mask : %s\n", binpad2 (mask, sizeof mask * CHAR_BIT));
printf ("\n masked : %s\n", binpad2 (masked, sizeof masked * CHAR_BIT));
printf ("\n | 123 : %s\n", binpad2 (y, sizeof y * CHAR_BIT));
masked |= y; /* apply the final or with 123 */
printf ("\n final : %s\n", binpad2 (masked, sizeof masked * CHAR_BIT));
return 0;
}
/** returns pointer to binary representation of 'n' zero padded to 'sz'.
* returns pointer to string contianing binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits.
*/
char *binpad2 (unsigned long n, size_t sz)
{
static char s[BITS_PER_LONG + 1] = {0};
char *p = s + BITS_PER_LONG;
register size_t i;
for (i = 0; i < sz; i++)
*--p = (n>>i & 1) ? '1' : '0';
return p;
}
Output
$ ./bin/bitsset
x : 11101010101010110101100100010010
& mask : 11111111111111111111111100000000
masked : 11101010101010110101100100000000
| 123 : 00000000000000000000000001111011
final : 11101010101010110101100101111011
How about using bit fields in C combined with a union? The following structure lets you set the whole 32-bit value, the top 10 bits or the bottom 22 bits. It isn't as versatile as a generic function but you can't easily make a mistake when using it. Be aware this and most solutions may not work on all integer sizes and look out for endianness as well.
union uu {
struct {
uint32_t bottom22 : 22;
uint32_t top10 : 10;
} bits;
uint32_t value;
};
Here is an example usage:
int main(void) {
union uu myuu;
myuu.value = 999999999;
printf("value = 0x%08x\n", myuu.value);
myuu.bits.top10 = 0;
printf("value = 0x%08x\n", myuu.value);
myuu.bits.top10 = 0xfff;
printf("value = 0x%08x\n", myuu.value);
return 0;
}
The output is:
value = 0x3b9ac9ff
value = 0x001ac9ff
value = 0xffdac9ff

Reading n-bit elements from a data stream in C

Given a data stream in C, I need to read the nth element which is x bits wide. x can vary from 1-64. How do I do this in C? I tried some bit fiddling but could not come up with a solution.
For example, for a data stream
01101010 11010101 11111111 00000010 00000000 10000000
==== ======
if the data is 10-bit wide and the element to parse is the third element. The expected data should be 1111 000000.
The data stream is byte-addressable.
First find out what the most significant bit represents. Specifically, does it represent bit 0 or bit 7 in your bit stream.
To find the nth element, you will need to find which byte it starts on ((n*x)/8), get the appropriate bits from that byte, then get the remaining bits from the following byte or bytes.
But, which bits should be taken from the bytes depends on what the most significant bit represents.
#include <stdio.h>
#include <stdint.h>
uint64_t bit_slice(const uint8_t ds[], int start, int end){
//index start, end {x | 1 <= x <= 64 }
uint64_t s = 0;//memcpy(&s, ds, 8);
int i, n = (end - 1) / 8;
for(i = 0; i <= n; ++i)
s = (s << 8) + ds[i];
s >>= (n+1) * 8 - end;
uint64_t mask = (((uint64_t)1) << (end - start + 1))-1;//len = end - start + 1
s &= mask;
return s;
}
int main(void){
uint8_t data[8] = {
0b01101010, 0b11010101, 0b11111111, 0b00000010, 0b00000000, 0b10000000 //0b... GCC extention
};
unsigned x = bit_slice(data, 21, 30);
printf("%X\n", x);//3C0 : 11 1100 0000
return 0;
}

Resources