Left shift using bitwise AND - c

The following lines of code Shift left 5 bits ie make bottom 3 bits the 3 MSB's
DWORD dwControlLocAddress2;
DWORD dwWriteDataWordAddress //Assume some initial value
dwControlLocAddress2 = ((dwWriteDataWordAddress & '\x07') * 32);
Can somebody help me understand how?

The 0x07 is 00000111 in binary. So you are masking the input value and getting just the right three bits. Then you are multiplying by 32 which is 2 * 2 * 2 * 2 * 2... which, if you think about it, shifting left by 1 is the same as multiplying by 2. So, shifting left five times is the same as multiplying by 32.

Multiplying by a power of two x is the same as left shifting by log2(x):
x *= 2 -> x <<= 1
x *= 4 -> x <<= 2
.
.
.
x *= 32 -> x <<= 5
The & doesn't do the shift - it just masks the bottom three bits. The syntax used in your example is a bit weird - it's using a hexadecimal character literal '\x07', but that's literally identical to hex 0x07, which in turn in binary is:
00000111
Since any bit ANDed with 0 yields 0 and any bit ANDed with 1 is itself, the & operation in your example simply gives a result of being the bottom three bits of dwWriteDataWordAddress.

It's a bit obtuse but essentially you're anding with 0x07 and then multiplying by 32 which is the same as shifting by 5. I'm not sure why a character literal is used rather than an integer literal but perhaps so that it is represented as a single byte rather than a word.
The equivalent would be:
( ( dw & 0x07 ) << 5 )
The & 0x07 masks off the first 3 bits and << 5 does a left shift by 5 bits.

& '\x07' - masks in the bottom three bits only (hex 7 is 111 in binary)
* 32 - left shifts by 5 (32 is 2^5)

Related

What does hibyte = Value >> 8 meaning?

I am using C for developing my program and I found out from an example code
unHiByte = unVal >> 8;
What does this mean? If unVal = 250. What could be the value for unHiByte?
>> in programming is a bitwise operation. The operation >> means shift right operation.
So unVal >> 8 means shift right unVal by 8 bits. Shifting the bits to the right can be interpreted as dividing the value by 2.
Hence, unHiByte = unval >> 8 means unHiByte = unVal/(2^8) (divide unVal by 2 eight times)
Without going into the shift operator itself (since that is answered already), here the assumption is that unVal is a two byte variable with a high byte (the upper 8 bits) and a low byte (the lower 8 bits). The intent is to obtain the value produced by ONLY the upper 8 bits and discarding the lower bits.
The shift operator though should easily be learned via any book / tutorial and perhaps was the reason some one down voted the question.
The >> is a bitwise right shift.
It operates on bits. With unHiByte = unVal >> 8; When unVal=250.
Its binary form is 11111010
Right shift means to shift the bits to the right. So when you shift 1111 1010, 8 digits to right you get 0000 0000.
Note: You can easily determine the right shift operation result by dividing the number to the left of >> by 2^(number to right of >>)
So, 250/28= 0
For example: if you have a hex 0x2A63 and you want to take 2A or you want to take 63 out of it, then you will do this.
For example, if we convert 2A63 to binary which is: 0010101001100011. (that is 16 bits, first 8 bits are 2A and the second 8 bits are 63)
The issue is that binary always starts from right. So we have to push the first 8 bits (2A) to the right side to be able to get it.
uint16_t hex = 0x2A63;
uint8_t part2A = (uint8_t)(hex >> 8) // Pushed the first
// eight bits (2A) to right and (63) is gone out of the way. Now we have 0000000000101010
// Now Line 2 returns for us 0x2A which the last 8 bits (2A).
// To get 63 we will do simply:
uint8_t part63 = (uint8_t)hex; // As by default the 63 is on the right most side in the binary.
It is that simple.

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

reading 2 bits off a register

I'm looking at a datasheet specification of a NIC and it says:
bits 2:3 of register contain the NIC speed, 4 contains link state, etc. How can I isolate these bits using bitwise?
For example, I've seen the code to isolate the link state which is something like:
(link_reg & (1 << 4))>>4
But I don't quite get why the right shift. I must say, I'm still not fairly comfortable with the bitwise ops, even though I understand how to convert to binary and what each operation does, but it doesn't ring as practical.
It depends on what you want to do with that bit. The link state, call it L is in a variable/register somewhere
43210
xxxxLxxxx
To isolate that bit you want to and it with a 1, a bitwise operation:
xxLxxxx
& 0010000
=========
00L0000
1<<4 = 1 with 4 zeros or 0b10000, the number you want to and with.
status&(1<<4)
This will give a result of either zero or 0b10000. You can do a boolean comparison to determine if it is false (zero) or true (not zero)
if(status&(1<<4))
{
//bit was on/one
}
else
{
//bit was off/zero
}
If you want to have the result be a 1 or zero, you need to shift the result to the ones column
(0b00L0000 >> 4) = 0b0000L
If the result of the and was zero then shifting still gives zero, if the result was 0b10000 then the shift right of 4 gives a 0b00001
so
(status&(1<<4))>>4 gives either a 1 or 0;
(xxxxLxxxx & (00001<<4))>>4 =
(xxxxLxxxx & (10000))>>4 =
(0000L0000) >> 4 =
0000L
Another way to do this using fewer operations is
(status>>4)&1;
xxxxLxxxx >> 4 = xxxxxxL
xxxxxxL & 00001 = 00000L
Easiest to look at some binary numbers.
Here's a possible register value, with the bit index underneath:
00111010
76543210
So, bit 4 is 1. How do we get just that bit? We construct a mask containing only that bit (which we can do by shifting a 1 into the right place, i.e. 1<<4), and use &:
00111010
& 00010000
----------
00010000
But we want a 0 or a 1. So, one way is to shift the result down: 00010000 >> 4 == 1. Another alternative is !!val, which turns 0 into 0 and nonzero into 1 (note that this only works for single bits, not a two-bit value like the link speed).
Now, if you want bits 3:2, you can use a mask with both of those bits set. You can write 3 << 2 to get 00001100 (since 3 has two bits set). Then we & with it:
00111010
& 00001100
----------
00001000
and shift down by 2 to get 10, the desired two bits. So, the statement to get the two-bit link speed would be (link_reg & (3<<2))>>2.
If you want to treat bits 2 and 3 (starting the count at 0) as a number, you can do this:
unsigned int n = (link_get & 0xF) >> 2;
The bitwise and with 15 (which is 0b1111 in binary) sets all but the bottom four bits to zero, and the following right-shift by 2 gets you the number in bits 2 and 3.
you can use this to determine if the bit at position pos is set in val:
#define CHECK_BIT(val, pos) ((val) & (1U<<(pos)))
if (CHECK_BIT(reg, 4)) {
/* bit 4 is set */
}
the bitwise and operator (&) sets each bit in the result to 1 if both operands have the corresponding bit set to 1. otherwise, the result bit is 0.
The problem is that isolating bits is not enough: you need to shift them to get the correct size order of the value.
In your example you have bit 2 and 3 for the size (I'm assuming that least significant is bit 0), it means that it is a value in range [0,3]. Now you can mask these bits with reg & (0x03<<2) or, converted, (reg & 0x12) but this is not enough:
reg 0110 1010 &
0x12 0000 1100
---------------
0x08 0000 1000
As you can see the result is 1000b which is 8, which is over the range. To solve this you need to shift back the result so that the least significant bit of the value you are interested in corresponds to the least significant bit of the containing byte:
0000 1000 >> 2 = 10b = 3
which now is correct.

c language bitwise trick

Here is code i saw in a C program , i knew this piece of code is to set a bit in the bit ASCII bit map corresponding to the character c.
field[ (c & 0x7f) >> 3 ] |= 1 << (c & 0x07);
field is an array of 16 characters, each character is 8 bits.
for example '97' is lower case 'a', if we set c to 97, then bit position 97 will be set to 1.
any one know why above code will set bit map corresponding to the character c?
and what are those magic number 0x7f, 0x07, 3 and 1 for?
If your array is 16 bytes long, it has 128 bits (16 x 8). So the first mask (0x7f) guarantees that you are only interested in the first 128 bits. Once you shift it 3 bits right, you have 4 bits left that are used to address your bitfield (the number ((c & 0x7F) >> 3 is a number between 0 and 15). So this part uses the upper 4 bits to address the byte.
Now, you need to address the bit in the byte, so you use the mask 0x07 to limit the value to the range 0 - 7 (corresponding to the bits 0 to 7). You use this number to shift the 1 so many positions.
At the end, you have a bit set in a position 0 to 127 (16 bytes of 8 bits). I hope this helps!
First, to clear up the magic numbers
0x7f is 0111 1111 in binary. This means the lower 7 bits of c are significant. This is then shifted by 3 so that only the original 0xxx x000 (4) bits are significant. But since these bits are shifted by 3 they count 0 to 15.
0x07 is 0000 0111 in binary. This means only the lower 3 bits are significant. The number 1 is shifted left by the value in these 3 bits, resulting a bit set in bit positions 0 to 7 within the byte.
In the end, the function only uses the lower 7 bits in the byte, which are the only significant bits in an ascii character. It uses the upper 4 for addressing the byte in the array and the bottom 3 to address the bit in the addressed byte.

What does >> and 0xfffffff8 mean?

I was told that (i >> 3) is faster than (i/8) but I can't find any information on what >> is. Can anyone point me to a link that explains it?
The same person told me "int k = i/8, followed by k*8 is better accomplished by (i&0xfffffff8);" but again Google didn't help m...
Thanks for any links!
As explained here the >> operator is simply a bitwise shift of the bits of i. So shifting i 1 bit to the right results in an integer-division by 2 and shifting by 3 bits results in a division by 2^3=8.
But nowadays this optimization for division by a power of two should not really be done anymore, as compilers should be smart enough to do this themselves.
Similarly a bitwise AND with 0xFFFFFFF8 (1...1000, last 3 bits 0) is equal to rounding down i to the nearest multiple of 8 (like (i/8)*8 does), as it will zero the last 3 bits of i.
Bitwise shift right.
i >> 3 moves the i integer 3 places to the right [binary-way] - aka, divide by 2^3.
int x = i / 8 * 8:
1) i / 8, can be replaced with i >> 3 - bitwise shift to the right on to 3 digits (8 = 2^3)
2) i & xfffffff8 comparison with mask
For example you have:
i = 11111111
k (i/8) would be: 00011111
x (k * 8) would be: 11111000
Therefore the operation just resets last 3 bits:
And comparable time cost multiplication and division operation can be rewritten simple with
i & xfffffff8 - comparison with (... 11111000 mask)
They are Bitwise Operations
The >> operator is the bit shift operator. It takes the bit represented by the value and shifts them over a set number of slots to the right.
Regarding the first half:
>> is a bit-wise shift to the right.
So shifting a numeric value 3 bits to the right is the same as dividing by 8 and inting the result.
Here's a good reference for operators and their precedence: http://web.cs.mun.ca/~michael/c/op.html
The second part of your question involves the & operator, which is a bit-wise AND. The example is ANDing i and a number that leaves all bits set except for the 3 least significant ones. That is essentially the same thing happening when you have a number, divide it by 8, store the result as an integer, then multiply that result by 8.
The reason this is so is that dividing by 8 and storing as an integer is the same as bit-shifting to the right 3 places, and multiplying by 8 and storing the result in an int is the same as bit-shifting to the left 3 places.
So, if you're multiplying or dividing by a power of 2, such as 8, and you're going to accept the truncating of bits that happens when you store that result in an int, bit-shifting is faster, operationally. This is because the processor can skip the multiply/divide algorithm and just go straight to shifting bits, which involves few steps.
Bitwise shifting.
Suppose I have an 8 -bit integer, in binary
01000000
If I left shift (>> operator) 1 the result is
00100000
If I then right shift (<< operator) 1, I clearly get back to wear I started
01000000
It turns out that because the first binary integer is equivelant to
0*2^7 + 1*2^6 + 0*2^5 + 0*2^4 + 0*2^3 + 1*2^2 + 0*2^1 + 0*2^0
or simply 2^6 or 64
When we right shift 1 we get the following
0*2^7 + 0*2^6 + 1*2^5 + 0*2^4 + 0*2^3 + 1*2^2 + 0*2^1 + 0*2^0
or simply 2^5 or 32
Which means
i >> 1
is the same as
i / 2
If we shift once more (i >> 2), we effectively divide by 2 once again and get
i / 2 / 2
Which is really
i / 4
Not quite a mathematical proof, but you can see the following holds true
i >> n == i / (2^n)
That's called bit shifting, it's an operation on bits, for example, if you have a number on a binary base, let's say 8, it will be 1000, so
x = 1000;
y = x >> 1; //y = 100 = 4
z = x >> 3; //z = 1
Your shifting the bits in binary so for example:
1000 == 8
0100 == 4 (>> 1)
0010 == 2 (>> 2)
0001 == 1 (>> 3)
Being as you're using a base two system, you can take advantage with certain divisors (integers only!) and just bit-shift. On top of that, I believe most compilers know this and will do this for you.
As for the second part:
(i&0xfffffff8);
Say i = 16
0x00000010 & 0xfffffff8 == 16
(16 / 8) * 8 == 16
Again taking advantage of logical operators on binary. Investigate how logical operators work on binary a bit more for really clear understanding of what is going on at the bit level (and how to read hex).
>> is right shift operation.
If you have a number 8, which is represented in binary as 00001000, shifting bits to the right by 3 positions will give you 00000001, which is decimal 1. This is equivalent to dividing by 2 three times.
Division and multiplication by the same number means that you set some bits at the right to zero. The same can be done if you apply a mask. Say, 0xF8 is 11111000 bitwise and if you AND it to a number, it will set its last three bits to zero, and other bits will be left as they are. E.g., 10 & 0xF8 would be 00001010 & 11111000, which equals 00001000, or 8 in decimal.
Of course if you use 32-bit variables, you should have a mask fitting this size, so it will have all the bits set to 1, except for the three bits at the right, giving you your number - 0xFFffFFf8.
>> shifts the number to the right. Consider a binary number 0001000 which represents 8 in the decimal notation. Shifting it 3 bits to the right would give 0000001 which is the number 1 in decimal notation. Thus you see that every 1 bit shift to the right is in fact a division by 2. Note here that the operator truncates the float part of the result.
Therefore i >> n implies i/2^n.
This might be fast depending on the implementation of the compiler. But it generally takes place right in the registers and therefore is very fast as compared to traditional divide and multiply.
The answer to the second part is contained in the first one itself. Since division also truncates all the float part of the result, the division by 8 will in theory shift your number 3 bits to the right, thereby losing all the information about the rightmost 3 bits. Now when you again multiply it by 8 (which in theory means shifting left by 3 bits), you are padding the righmost 3 bits by zero after shifting the result left by 3 bits. Therefore, the complete operation can be considered as one "&" operation with 0xfffffff8 which means that the number has all bits 1 except the rightmost 4 bits which are 1000.

Resources