1. First question
Before starting this article, let's first give a question given by an interviewer, a C language magnate during the webmaster's interview a few days ago:
int i = 255;
i <<= 24;
i >>= 24;
** Question: **
- 最终
i等于多少? - 如果
i是uint类型,最终i结果是多少?
2. C#bit operation
C#bit arithmetic is a powerful tool that can play an important role in processing binary data and bit operations. By using bit operators, we can perform bit-level operations on integers, such as bit AND, bit OR, bit XOR, and bit negation. Bit operations can be used to optimize performance, compress data, implement bit masks and bit flags, etc. Understanding and mastering the basic principles and common application scenarios of C#bit operations will allow us to process binary data more efficiently and in some cases improve the performance and readability of the code. By deeply understanding C#bit operations, we can exercise greater creativity and flexibility in programming.
本节内容主要参考文章:C# 中使用位运算(与、或、非 & | ^)进行数据校验和c# 位运算符_c#位运算符-CSDN博客。
To learn bit operations, we must first understand what bit operations are? Everything in the program is stored in binary form in computer memory (i.e., 0 or 1). Bit operation is to directly operate on every bit of binary numbers in memory.
In C#, you can perform bitwise logical operations on integer operand objects. The meaning of performing logical operations by bits means that each bit of the object being operated is taken in turn and the logical operation is performed, and the logical operation result of each bit is each bit of the result value. The bitwise logical operators supported by C#are shown in the table.
| sign of operation | significance | operand type | Operation result type | number of objects | examples |
|---|---|---|---|---|---|
| ~ | Bit logic ** NOT ** operation, bit-negated | integer type, character type | integer | 1 | ~a |
| & | Bitwise logical ** and ** operations actually have similarities with the && logical operator | ibid. | ibid. | 2 | a & b |
| | | Bit logical ** or ** operation, same as||There are similar places | ibid. | ibid. | 2 | a | b |
| ^ | Bit logic ** XOR ** operation | ibid. | ibid. | 2 | a ^ b |
| << | Bit ** left shift ** operation | ibid. | ibid. | 2 | a<<4 |
| >> | Bit ** right shift ** operation | ibid. | ibid. | 2 | a>>2 |
2.1. ~: Bit logical NOT operation
Bitwise logical NOT operations are single-purpose and have only one operand. Bit logical non-operation performs a non-operation on the value of the operand bitwise, that is, if a bit is equal to 0, it is converted to 1; if a bit is equal to 1, it is converted to 0.
For example, if a bit logic negation is performed on binary 10010001, the result is equal to 01101110, which is expressed in decimal terms:
~145 is equal to 110; binary 01010101 is logically negated, and the result is equal to 10101010. In decimal terms,~85 equals 176.
int a = 1001 0001; // 十进制:145
int b = ~a; // b = 0110 1110,即十进制:110
来复杂的,看这篇文章c# 位运算符_c#位运算符-CSDN博客:
int a = 13;
int b = -14;
Console.WriteLine(~a); // -14
Console.WriteLine(~b); // 13;
How to operate binary? First of all, we must remember some principles:
| Original code * | complement | complement ** | negated | |
|---|---|---|---|---|
| positive number | Sign bit + absolute value | original code | original code | 0,1 swap |
| 13 | 0 1101 | 0 1101 | 0 1101 | 1 0010 |
| negative | Sign bit + absolute value | Absolute value inversion | Reverse code +1 | 0,1 swap |
| -14 | 1 1110 | 1 0001 | 1 0010 | 0 1101 |
- : The length of the sign bit is related to the type definition. The sign bit of int in C#is 1 bit **: Values in C#are stored in complement
The following shows how to convert the original codes between the two
int b = 1 1110; // 前面的1表示符号位
反码 = 1 0001; // 符号位不变
补码 = 1 0010; // 反码加1
补码取反 = 0 1101; // 得到新的反码就是结果a,连同符号位一起反)
int a = 0 1101;
a的补码 = 0 1101;
补码取反 = 1 0010; // 此时为b的补码了
补码转反码 = 1 0001; // 即减1
反码转原码 = 1 1110; // 就是结果b的源码
After many experiments, a rule was obtained:
~(+a)= -(a+1);(To invert a positive number, you only need to add 1 to the current number and change it to negative)
~(-a)= (+a-1);(To invert negative numbers, you only need to treat the current number as a positive number first, and then subtract 1 to get the result)
2.2. $: Bit logic and operation
Bitwise logical AND operates bitwise ANDs on two operands. Rules for AND operations: 1 and 1 are equal to 1, 1 and 0 are equal to 0.
Example code:
int a = 13;
int b = 14;
int result = a & b; // 12
Convert to binary:
int a = 0000 1101;
int b = 0000 1110;
int result = 0000 1100;
The & operator compares 0 and 1 in the same binary position. When the numbers in the same position are the same, it returns the same number, otherwise it returns 0. Is it similar to the && operator returns True if it determines that the two bools are consistent, otherwise it returns False? So we get the result of result, which translates to decimal to 12.
2.3. |: Bit logical OR operation
Bitwise logical OR operations bitwise ORs two operands. The rule for the OR operation is: 1 or 1 equals 1, 1 or 0 equals 1,
Example code:
int a = 13;
int b = 14;
int result = a | b; // 15
Convert to binary:
int a = 0000 1101;
int b = 0000 1110;
int result = 0000 1111;
In fact, the judgment method is the same, except that the results returned are different.| The operator determines two binary positions of 0 and 1, and returns 1 as long as the digit in one position is 1. Is it and|| Operators are also very similar. As long as one True is returned to True, and then the resulting result is converted to decimal 15.
2.4. ^: Bit logic exclusive-OR operation
Bitwise logical exclusive-OR operations bitwise exclusive-ORs two operands. The rules for exclusive OR operation are: 1 XOR 1 equals 0,
1 XOR 0 equals 1, and 0 XOR 0 equals 0. That is, if you are identical, you will get 0, if you are different, you will get 1.
Example code:
int a = 13;
int b = 14;
int result = a ^ b; // 3
Convert to binary:
int a = 0000 1101;
int b = 0000 1110;
int result = 0000 0011;
It can be seen from this that when ^judges the numbers above the same position, if the two numbers are the same, both 0 and 1 will be returned, and 1 will be returned if either of them is 1. and| Yes, as long as there is one, it returns 1 as long as the one in the position is 1, so the name is called XOR (different returns OR).
2.5. <<: Bit shift left operation
位左移运算将整个数按位左移若干位,左移后空出的部分0。比如:8位的byte型变量byte a=0x65(即二进制的01100101),将其左移3位:a<<3的结果是0x27(即二进制的00101000)。
byte a = 0110 0101;
a <<= 3;//0010 1000
Move the first operand to the left by the number of digits specified by the second operand, and make up the empty position. Shifting left is equivalent to multiplication. Moving one digit to the left is equivalent to multiplying 2; moving two digits to the left is equivalent to multiplying 4; and moving three digits to the left is equivalent to multiplying 8.
x<<1= x*2
x<<2= x*4
x<<3= x*8
x<<4= x*16
2.6. >>: Bit right shift operation
位右移运算将整个数按位右移若干位,右移后空出的部分填0。比如:8位的byte型变量byte a=0x65(既(二进制的01100101))将其右移3位:a>>3的结果是0x0c(二进制00001100)。
byte a = 0110 0101;
a >>= 3;//0000 1100
Move the first operand to the right by the number of digits specified by the second operand, and make up the empty position.
Moving right is equivalent to dividing. Shifting one digit to the right is equivalent to dividing by 2; shifting two digits to the right is equivalent to dividing by 4; shifting three digits to the right is equivalent to dividing by 8.
x>>1= x/2
x>>2= x/4
x>>3= x/8
x>>4= x/16
3. Summary and answers to questions
看微软文档位运算符和移位运算符两点注意
- 位运算和移位运算永远不会导致溢出,并且不会在已检查和未检查的上下文中产生相同的结果。
- 移位运算符仅针对
int、uint、long和ulong类型定义,因此运算的结果始终包含至少 32 位。如果左侧操作数是其他整数类型(sbyte、byte、short、ushort或char),则其值将转换为int类型。
Here are the answers to the questions at the beginning of the article and the answer analysis to end this article:
int i = 255; // 00000000 00000000 00000000 11111111
i <<= 24; // 11111111 00000000 00000000 00000000
i >>= 24; // 11111111 11111111 11111111 11111111;
修改i数据类型为uint:
uint i = 255; // 00000000 00000000 00000000 11111111
i <<= 24; // 11111111 00000000 00000000 00000000
i >>= 24; // 00000000 00000000 00000000 11111111;
int和uint位移后结果不同的原因:
- For a right-shift operation of signed integers, the most significant sign bit is also right-shifted. This means that if the most significant bit of the original value is 1, then after shifting to the right, the sign bit will be retained, i.e. padded with 1. This right shift operation is called arithmetic right shift.
- For right-shifting operations of unsigned integers, the sign bit is not retained, but the most significant 0 is also right-shifted. This right shift operation is called a logical right shift.
** If there are any mistakes in this article, please correct them. References in this article: **