1. bitwise and operation bitwise AND operator "&" are binary operators. Its function is the binary phase corresponding to the two numbers involved in the operation. The result bit is 1 only when the two binary numbers are 1. Otherwise, the result bit is 0. The number of involved operations is supplemented.
For example, 9 & 5 can be written as follows: 00001001 (Binary complement of 9) & 00000101 (Binary complement of 5) 00000001 (Binary complement of 1) Visible 9 & 5 = 1.
Bitwise AND operations are usually used to clear some bits or retain some bits. For example, if a clears the high eight bits of 0 and retains the low eight bits, it can be used as a & 255 operation (255 of the binary number is 0000000011111111 ).
Application:
A. Reset the special location (the position in the mask is 0, and the other bit is 1, s = s & mask)
B. Locate a specified position in a specified number (mask: 1; other bits are 0, s = s & mask)
2. bitwise OR operator "|" is a binary operator. Its function is the binary phase or corresponding to the two numbers involved in the operation. If one of the two binary numbers is 1, The result bit is 1. The two numbers involved in the operation appear as a complement.
For example, 9 | 5 can be written as follows:
00001001 | 00000101
00001101 (decimal 13) Visible 9 | 5 = 13
Application:
It is often used to set the source operand to some positions of 1, and the other BITs remain unchanged. (In mask, the specific position is 1, and the other bit is 0 s = s | mask)
3. bitwise exclusive or operation bitwise exclusive OR operator "^" is a binary operator. This function is used to calculate whether the binary numbers corresponding to the binary numbers are different or not. When the binary numbers of the two numbers are different, the result is 1. The number of involved operations still appears as a complement. For example, 9 ^ 5 can be written as follows:
00001001 ^ 00000101 00001100 (12 in decimal format)
Application:
A. Reverse the value of the special location (1 in the specific position of the mask, and 0 s = s ^ mask in other places)
B. Do not introduce the third variable and exchange the values of the two variables (set a = A1, B = B1)
Status after Operation
A = A1 ^ B1 A = a ^ B a = A1 ^ B1, B = b1
B = A1 ^ B1 ^ B1 B = a ^ B a = A1 ^ B1, B = A1
A = b1 ^ A1 ^ A1 A = a ^ B a = b1, B = A1
4. Inverse Calculation
Inverse Operator ~ It is a single object operator and has the right combination. This function is used to reverse the binary numbers involved in the operation by bit. Example ~ 9 is calculated as follows :~ (0000000000001001) Result: 1111111111110110
5. Left shift operation
The Left shift operator <is a binary operator. Its function shifts the binary numbers on the left of "<" to several places left. The number on the right of "<" indicates the number of digits to be moved, Which is discarded at a high position and supplemented by 0 at a low position. The value is equal to 2. For example, a <4 refers to moving each binary of a four places to the left. For example, if a = 00000011 (decimal 3), after four digits are left removed, the value is 00110000 (decimal 48 ).
6. Right Shift operation
The right shift operator ">" is a binary operator. Its function is to shift all the binary numbers on the left of ">" to several places right, and the right of ">" to the specified number of digits. The value is equivalent to Division 2.
For example, if a = 15, A> 2, 000001111 is shifted to 00000011 (decimal 3 ). For the vacant positions removed from the left, if it is a positive number, the vacant space is supplemented with 0. If it is a negative number, it may be supplemented with 0 or 1, depending on the computer system used. Moving 0 is called logical right shift, and moving 1 is called arithmetic right shift. Turbo C uses logical right shift.
Main (){
Unsigned A, B;
Printf ("input a number :");
Scanf ("% d", & );
B = a> 5;
B = B & 15;
Printf ("a = % d B = % d", a, B );
}
Let's look at another example:
Main (){
Char a = 'A', B = 'B ';
Int p, c, d;
P =;
P = (p <8) | B;
D = p & 0xff;
C = (p & 0xff00)> 8;
Printf ("a = % d B = % d c = % d", a, B, c, d );
}
Floating Point storage format:
The storage format of floating point numbers is symbol + level code (Fixed Point integer) + ending number (Fixed Point decimal)
Seeeeeeeemmmmmmmmmmmmmmmmmmmmm
That is, 1-bit sign bit (0 is positive, 1 is negative), 8-bit index bit, 23-bit ending number bit
Before floating point data is stored, it is first converted to the k-power form of 2, namely:
F = A1 * 2 ^ k + A2 * 2 ^ (k-1) +... + Ak +... + An * 2 ^ (-m) (Ai = {0, 1}, A1 = 1)
For example, 5.5 = 2 ^ 2 + 2 ^ 0 + 2 ^ (-1)
K is the index, and after 127 is added, it forms an 8-digit index.
The index of 5.5 is 2 + 127 = 129 = 10000001
A2A3... An is the ending number. If it is less than 23 digits, it is supplemented with 0.
So 5.5 = 01000000101000000000000000000000 = 40A00000
Therefore, for floating-point numbers * 2 and/2, you only need to pair the 8-bit symbol bit + and-, but not move left or right.
For the differences between the bitwise operations of unsigned int and int, the following example on CU is clearly described:
[Problem]: Is there any problem with this function?
/**
* This function concatenates two 16-bit values into a 32-bit value.
* Parameter: the height of sHighBits is 16 bits.
* SLowBits 16-bit low
* Return value: 32-bit value
**/
Long CatenateBits16 (short sHighBits, short sLowBits)
{
Long lResult = 0;/* Temporary Variable with 32-bit values */
/* Place the first 16-bit value into the 16-bit height of the 32-bit value */
LResult = sHighBits;
LResult <= 16;
/* Clear 16-bit low 32-bit values */
LResult & = 0xFFFF0000;
/* Put the second 16-bit value into the lower 16-bit value of the 32-bit value */
LResult | = (long) sLowBits;
Return lResult;
}
//////////////////////////////////////// /////////
[Problem Discovery]:
Let's take a look at the following test code:
//////////////////////////////////////// /////////
Int main ()
{
Short sHighBits1 = 0x7fff;
Short sHighBits2 = 0x8f12;
Unsigned short usHighBits3 = 0xff12;
Short sLowBits1 = 0x7bcd;
Long lResult = 0;
Printf ("[sHighBits1 + sLowBits1]";
LResult = CatenateBits16 (sHighBits1, sLowBits1 );
Printf ("lResult = % 08x", lResult, lResult );
LResult = CatenateBits16 (sHighBits2, sLowBits1 );
Printf ("lResult = % 08x", lResult, lResult );
LResult = CatenateBits16 (usHighBits3, sLowBits1 );
Printf ("lResult = % 08x", lResult, lResult );
}
//////////////////////////////////////// /////////
The running result is:
[SHighBits1 + sLowBits1]
LResult = 7fff7bcd
LResult = 8f1_bcd
LResult = ffw.bcd
Well, the operation is correct ...... So we can safely use this function in our own program.
However, one day, one of our programs did not produce any correct results! After n hours of inspection and debugging, I finally tracked the results ...... CatenateBits16 ()!? The returned value is incorrect !!
"Depressing !" You said, "How can this function be faulty !?"
However, what is even more depressing is still behind the scenes, because you take the input in the program as a parameter and perform one-step debugging in a simple main:
//////////////////////////////////////// /////////
Int main ()
{
Short sHighBits1 = 0x7FFF;
Short sHighBits2 = 0x8F12;
Unsigned short usHighBits3 = 0x8F12;
Short sLowBits1 = 0x7BCD; // The parameters you actually use
Short sLowBits2 = 0x8BCD; // The parameter you actually use
Long lResult = 0;
Printf ("[sHighBits1 + sLowBits1]";
LResult = CatenateBits16 (sHighBits1, sLowBits1 );
Printf ("lResult = % 08x", lResult, lResult );
LResult = CatenateBits16 (sHighBits2, sLowBits1 );
Printf ("lResult = % 08x", lResult, lResult );
LResult = CatenateBits16 (usHighBits3, sLowBits1 );
Printf ("lResult = % 08x", lResult, lResult );
Printf ("[sHighBits1 + sLowBits2]";
LResult = CatenateBits16 (sHighBits1, sLowBits2 );
Printf ("lResult = % 08x", lResult, lResult );
LResult = CatenateBits16 (sHighBits2, sLowBits2 );
Printf ("lResult = % 08x", lResult, lResult );
LResult = CatenateBits16 (usHighBits3, sLowBits2 );
Printf ("lResult = % 08x", lResult, lResult );
Return 0;
}
//////////////////////////////////////// /////////
The result is:
[SHighBits1 + sLowBits1]
LResult = 7fff7bcd
LResult = 8f1_bcd
LResult = 8f1_bcd
[SHighBits1 + sLowBits2]
LResult = ffff8bcd // oops!
LResult = ffff8bcd // oops!
LResult = ffff8bcd // oops!
The last time it was good, the last time it was ffff? XFile?
[X file Truth]:
Note that the two are used as sLowBits1 and sLowBits2 with a low 16-bit value.
Known:
When sLowBits1 = 0x7bcd is used, the function returns the correct value;
When sLowBits2 = 0x8bcd is used, X Files are generated in the function.
So what is the difference between sLowBits1 and sLowBits2?
Note that sLowBits1 and sLowBits2 are both short (rather than unsigned short), so here sLowBits1 represents a positive value, while sLowBits2 represents a negative value (because 8 is binary 1000, sLowBits2 has a maximum of 1 ).
Let's look at the CatenateBits16 () function:
//////////////////////////////////////// /////////
Long CatenateBits16 (short sHighBits, short sLowBits)
{
Long lResult = 0;/* Temporary Variable with 32-bit values */
/* Place the first 16-bit value into the 16-bit height of the 32-bit value */
LResult = sHighBits;
LResult <= 16;
/* Clear 16-bit low 32-bit values */
LResult & = 0xFFFF0000;
/* Put the second 16-bit value into the lower 16-bit value of the 32-bit value */
LResult | = (long) sLowBits; // pay attention to this sentence !!!!
Return lResult;
}
//////////////////////////////////////// /////////
If we use
Printf ("sLowBits = % 04x", sLowBits );
Print the input sLowBits value and you will find
When sLowBits = 0x7bcd, the print result is
SLowBits = 7bcd
When sLowBits = 0x8bcd, the print result is
SLowBits = ffff8bcd
Yes, that is, use % 04x to print the 8-bit hexadecimal format.
Therefore, we can see that:
When sLowBits = 0x8bcd, the "lResult | = (long) sLowBits;" statement in the function will be converted
0xffff8bcd
And then perform the or operation with lResult. Because the current lResult value is 0xXXXX0000 (XXXX is any value), it is clear that no matter what sHighBits is, the final result will be
0xffff8bcd
When sLowBits = 0x7bcd, the "lResult | = (long) sLowBits;" statement in the function will first convert sLowBits
0x00007bcd
And then perform the or operation with lresult. The result of this or operation is correct.
That is to say, catenatebits16 () is normal when the highest bit of slowbits is 0, and a deviation occurs when the highest bit is 1.
[Lesson: in some cases, when bitwise operations and bitwise processing are performed, consider using unsigned values-because symbols are often not processed at this time. Even if you need a signed value, you should consider converting it before and after calling catenatebits16 (). After all, the signed value is quite strange in bit processing.]
The following catenatebits16 () version should be better:
//////////////////////////////////////// /////////
Unsigned long catenatebits16 (unsigned short shighbits, unsigned short slowbits)
{
Long lresult = 0;
/* Place the first 16-bit value into the 16-bit height of the 32-bit value */
Lresult = shighbits;
Lresult <= 16;
/* Clear 16-bit low 32-bit values */
Lresult & = 0xffff0000;
/* Put the second 16-bit value into the lower 16-bit value of the 32-bit value */
Lresult | = (long) slowbits & 0x0000ffff;
Return lresult;
}
//////////////////////////////////////// /////////
Note "lResult | = (long) sLowBits & 0x0000FFFF ;". In fact, even if we declare the parameter (especially sLowBits) of the CatenateBits16 () function as short, the result will be correct.