Omit leading 0 in char and append - c

Say I have these 8 bit chars:
01111111 00011100 01101111
I want to omit the leading 0 and append the bits from char before like so:
11111110 01110011 01111000
*note that the last char has been padded with zeros.
Any advice on how to do this would be much appreciated. cheers.

Shift the first char up 1:
num[0] << 1;
This will turn 01111111 into 11111110. Now you need to OR the LSB with the MSB of the next char. To do that you need a shifted copy of the next char:
char copy = num[1] >> 7;
This would turn 01110011 into 00000000, since it's high bit was 0. You can now OR the two:
num[0] |= num[1];
Which will give you what you want.
To do this with a sequence, you would need to loop and increase the shifts at each iteration up to 8, then reset.
Note that as chux points out, you are best off using unsigned types for stuff like this.

Related

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.
}

C - Using bit-shift operators for base conversion

I'm trying to convert some data from hex to base64 in C, I found an algorithm online but I would really like to know how it works rather than just implenting it and firing it off. If someone could please explain how the following is working I would appreciate it. I have been reading about the shift operators and I don't seem to understand them as much as I thought I did...it's not quite clicking for me.
for (x = 0; x < dataLength; x += 3)
{
/* these three 8-bit (ASCII) characters become one 24-bit number */
n = data[x] << 16;
if((x+1) < dataLength)
n += data[x+1] << 8;
if((x+2) < dataLength)
n += data[x+2];
/* this 24-bit number gets separated into four 6-bit numbers */
n0 = (uint8_t)(n >> 18) & 63;
n1 = (uint8_t)(n >> 12) & 63;
n2 = (uint8_t)(n >> 6) & 63;
n3 = (uint8_t)n & 63;
This code was taken from Wikibooks, it is NOT mine, I'm just trying to understand the bitshifting and how it's allowing me to convert the data.
Thank you for your help, I really appreciate it.
Source: Base64
First of all, the input data is not hex as you say. It's simply data stored as bytes. The code will give you the base64 representation of it (although the code you posted lacks the part which will map n0, n1, n2, n3 to printable ASCII characters).
Suppose the first three bytes of the input are (in binary representation, each letter represents a 0 or 1):
abcdefgh, ijklmnop, qrstuvwx
The first part of the code will combine them to a single 24-bit number. This is done by shifting the first one 16 bits to the left and the second one 8 bits to the left and adding:
abcdefgh0000000000000000 (abcdefgh << 16)
+ 00000000ijklmnop00000000 (ijklmnop << 8)
0000000000000000qrstuvwx
------------------------
abcdefghijklmnopqrstuvwx
Then it separates this into four 6-bit numbers by shifting and and'ing. For example, the second number is calculated by shifting 12 bits to the right and and'ing with 111111
n = abcdefghijklmnopqrstuvwx
n>>12 = 000000000000abcdefghijkl
63 = 000000000000000000111111
And'ing gives:
000000000000000000ghijkl
Ok here is a bit of explanation..
data[x] is an array of chars, a char is usuall 8bits.. (random 8bits number 01010101)
n is a 32bit number here is a random 32bit number(01011111000011110000111100001111)think there are 32bits there :)
remember n is 32bits and data is only 8bits.. lets go through the first line
n = data[x] << 16;
<<16 has precedence over the equal sign so its evaluated first.
data[x] << 16 means move the bits in memory that data[x] represents by 16bits to the left.
suppose data[x] = 'a' this is represented by 01100001 in memory(1 bytes), so lets move is 16bits to the left
n = 00000000 01100001 00000000 00000000
next we have
if((x+1) < dataLength)
n += data[x+1] << 8;
this says move the next char data[x+1] 8 bits and add it to n; so lets move it 8 bits first
( I assumed it was 'a' again)
00000000 00000000 01100001 00000000
(this is done in some register in your processor)
now lets add it to n
00000000 01100001 01100001 00000000
next part is
if((x+2) < dataLength)
n += data[x+2];
lets do the same thing here, notice there is no bit shifting, since the last 8bits of n are free!! all we need to do is add it to n
b = 01100010 (assumed data[x+2] = 'b')
adding it to n
00000000 01100001 01100001 01100010
great so now we have a 24bits number(actually n is 32bits but the last 24bits is what we need)
next part
n0 = (uint8_t)(n >> 18) & 63;
(take note n0 is only 8bits wide or a single unsigned byte)
take n and move it to the left by 18bits and "and" it with 63
n = 00000000 01100001 01100001 01100010
n moved 18bits to right is 00000000 00000000 00000000 00011000
now n is cast to an unsigned int of 8bits (uint8_t)
so now it becomes 00011000
last part is the & operator(bitwise and)
00011000 &
00111111
n0= 00011000
now repeat this for the rest

How to flip a specific bit in a byte in C?

I'm trying to use masks and manipulating specific bits in a byte.
For example:
I want to write a program in C that flips two bits at particular positions e.g. the bit at position 0 and the one at the third position.
So, 11100011, would become 01110011.
How can I swap these bits?
Flipping a bit is done by XOR-ing with a mask: set bits at the positions that you want to flip, and then execute a XOR, like this:
int mask = 0x90; // 10010000
int num = 0xE3; // 11100011
num ^= mask; // 01110011
Here are a few notes:
bits are commonly counted from the least significant position, so your example flips bits in positions 4 and 7, not at positions 0 and 4
To construct a bit mask for a single position, use expression 1 << n, where n is the position number counting from the least significant bit.
To combine multiple bits in a single mask, use | operator. For example, (1 << 4) | (1 << 7) constructs the mask for flipping bits 4 and 7.
If your byte is x, and you want to switch the bits at the i-th and j-th position:
x = x ^ ((1<<i) | (1<<j));
So, in your case, it would just be (1<<4) | (1<<7). :)
First of all, good luck!
One remark - it is more useful to count the bits from the right and not left, since there are various byte/word sizes (8-bit,16-bit,etc.) and that count preserves compatibility better. So in your case you are referring to bits #7 and #4 (zero-count).
Did you mean 'flip' (change 0<->1 bits) or 'switch' them between one and the other?
For the first option, the answer above (XOR with "int mask = 0x90; // 10010000") is very good. For the second one, it's a bit more tricky (but not much).
To flip bits, you can use the exclusive OR bitwise operator. This takes two operands (typically, the value you want to operate on and the mask defining what bits will be flipped). The eXclusive OR (XOR) operator will only flip a bit if, and only if, one of the two is set to 1, but NOT both. See the (simple) example below:
#include <stdio.h>
int main(int argc, char** argv)
{
int num = 7; //00000111
int mask = 3; //00000011
int result = num ^ mask; //00000100
printf("result = %d\n", result); //should be 4
return 0;
}

Understanding shifting and logical operations

I am trying to read the 'size' of an SD card. The sample example which I am having has following lines of code:
unsigned char xdata *pchar; // Pointer to external mem space for FLASH Read function;
pchar += 9; // Size indicator is in the 9th byte of CSD (Card specific data) register;
// Extract size indicator bits;
size = (unsigned int)((((*pchar) & 0x03) << 1) | (((*(pchar+1)) & 0x80) >> 7));
I am not able to understand what is actually being done in the above line where indicator bit is being extracted. Can somebody help me in understanding this?
The size is made up of bits from two bytes. One byte is at pchar, the other at pchar + 1.
(*pchar) & 0x03) takes the 2 least significant bits (chopping of the 6 most significant ones).
This result is shifted one bit to the left using << 1. For example:
11011010 (& 0x03/00000011)==> 00000010 (<< 1)==> 00000100 (-----10-)
Something similar is done with pchar + 1. For example:
11110110 (& 0x80/10000000)==> 10000000 (>> 7)==> 00000001 (-------1)
Then these two values are OR-ed together with |. So in this example you'd get:
00000100 | 00000001 = 00000101 (-----101)
But note that the 5 most significant bits will always be 0 (above indicated with -) because they were &-ed away:
To summarize, the first byte holds two bits of size, while the second byte only one bit.
It seems the size indicator, say SI, consists of 3 bits, where *pchar contains the two most significant bits of SI in its lowest two bits (0x03) and *(pchar+1) contains the least significant bit of SI in its highest bit (0x80).
The first and second line figure out how to point to the data that you want.
Let's now go through the steps involved, from left to right.
The first portion of the operations takes the byte pointed to by pchar, performs a logical AND on the byte and 0x03 and shifts over that result by one bit.
That result is then logically ORed with the next byte (*pchar+1), which in turn is ANDed with 0x80, which is then right shifted by seven bits. Essentially, this portion just strips off the first bit in the byte and shifts it over by seven bits.
What the result is essentially this:
Imagine pchar points to the byte where bits are represented by letters: ABCDEFGH.
The first part ANDs with 0x03, so we are left with 000000GH. This is then left shifted by one bit, so we are left with 00000GH0.
Same thing for the right portion. pchar+1 is represented by IJKLMNOP. With the first logical AND, we are left with I0000000. This is then right shifted seven times. So we have 0000000I. This is combined with the left hand portion using the OR, so we have 00000GHI, which is then casted into an int, which holds your size.
Basically, there are three bits that hold the size, but they are not byte aligned. As a result, some manipulation is necessary.
size = (unsigned int)((((*pchar) & 0x03) << 1) | (((*(pchar+1)) & 0x80) >> 7));
Can somebody help me in understanding this?
We have byte *pchar and byte *(pchar+1). Each byte consists of 8 bits.
Let's index each bit of *pchar in bold: 76543210 and each bit of *(pchar+1) in italic: 76543210.
1.. ((*pchar) & 0x03) << 1 means "zero all bits of *pchar except bits 0 and 1, then shift result to the left by 1 bit":
76543210 --> xxxxxx10 --> xxxxx10x
2.. (((*(pchar+1)) & 0x80) >> 7) means "zero all bits of *(pchar+1) except bit 7, then shift result to the right by 7 bits":
76543210 --> 7xxxxxxx --> xxxxxxx7
3.. ((((*pchar) & 0x03) << 1) | (((*(pchar+1)) & 0x80) >> 7)) means "combine all non-zero bits of left and right operands into one byte":
xxxxx10x | xxxxxxx7 --> xxxxx107
So, in the result we have two low bits from *pchar and one high bit from *(pchar+1).

Left shift operator in C

Consider:
#include <stdio.h>
#define macro(a) a=a<<4;
main()
{
int a = 0x59;
printf("%x", a);
printf("\n");
macro(a)
printf("%x", a);
}
For the above code, I am getting the below output:
59
590
Why am I not getting the below output as the left shift operation?
59
90
Left shifts do not truncate the number to fit the length of the original one. To get 90, use:
(a<<4) & 0xff
0x59 is an int and probably on your platform it has sizeof(int)==4. Then it's a 0x00000059. Left shifting it by 4 gives 0x00000590.
Also, form a good habit of using unsigned int types when dealing with bitwise operators, unless you know what you are doing. They have different behaviours in situations like a right shift.
You shifted a hexadecimal number by 4 places to left so you get 590, which is correct.
You had
000001011001
shifted to left by 4 bits
010110010000
is 590 in hexadecimal
10010000
is 90 in hexadecimal, so you might want to remove 0101 as is shown by phoeagon.
In your printf, if you change %x to %d, you get a = 89.
And after left shifting you will get a = 1424.
Generally for decimal (base 10) numbers
a = a<< n is a = a*2^n
a = a>> n is a = a/2^n
For hexadecimal (base 16) numbers, any shift by n (left or right), can be considered, as a corresponding shift of the digits of the binary equivalent. But this depends on sizeof(int), used for a given compiler.
You are using int, so you have:
000001011001
If you shift it by 4 to the left, you get
010110010000
If you only want to have only the first 8 bits you don't have to use "int" but unsigned char (or char):
#include<stdio.h>
#define macro(a) a=a<<4;
main()
{
unsigned char a=0x59;
printf("%x",a);
printf("\n");
macro(a)
printf("%x",a);
}
If you still want to use int, but only keep the first 8 bits, you can use a mask:
#define macro(a) a=(a<<4) & 0xFF
So could you please tell me what should I do so as to get the output
as 0x90? I need to shift the last 4 bits to the first 4 bits adding 0's
at the end
The only way you can shift the 4 last bit 4 bit to the left AND get it in the place of the first 4 bit is if your type have just 8 bit. Usually this is the case of unsigned char, not int. You will get 0x90 for
unsigned char a=0x59;
macro(a)
but when using int the result is 0x590
The error is not with the use of the << is with the selection of the type. (or a misuse of macro?)

Resources