深入理解c#位運算:掌握位運算符的妙用

深入理解c#位運算:掌握位運算符的妙用

c#位運算是一種強大的工具,可以在處理二進位數據和位操作時發揮重要作用。通過使用位運算符,我們可以對整數進行位級別的操作,如位與、位或、位異或和位取反等。位運算可以用於優化性能、壓縮數據、實現位掩碼和位標誌等。了解和掌握c#位運算的基本原理和常見應用場景,將使我們能夠更高效地處理二進位數據,並在某些情況下提高代碼的性能和可讀性。通過深入理解c#位運算,我們可以在編程中發揮更大的創造力和靈活性。

最后更新 2023/11/6 下午11:15
沙漠尽头的狼
预计阅读 9 分钟
分类
.NET
标签
.NET C# 位運算

1. 開頭一問

本文開始前,先給出站長前幾天面試,一位面試官c語言大佬給的一題:

int i = 255;
i <<= 24;
i >>= 24;

問題:

  1. 最终i 等于多少?
  2. 如果iuint类型,最终i结果是多少?

2. c#位運算

c#位運算是一種強大的工具,可以在處理二進位數據和位操作時發揮重要作用。通過使用位運算符,我們可以對整數進行位級別的操作,如位與、位或、位異或和位取反等。位運算可以用於優化性能、壓縮數據、實現位掩碼和位標誌等。了解和掌握c#位運算的基本原理和常見應用場景,將使我們能夠更高效地處理二進位數據,並在某些情況下提高代碼的性能和可讀性。通過深入理解c#位運算,我們可以在編程中發揮更大的創造力和靈活性。

本节内容主要参考文章:C# 中使用位运算(与、或、非 & | ^)进行数据校验c# 位运算符_c#位运算符-CSDN博客

要學會位運算,首先要清楚什麼是位運算?程式中的所有內容在計算機內存中都是以二進位的形式儲存的(即:0或1),位運算就是直接對在內存中的二進位數的每位進行運算操作。

在c#中可以對整型運算對象按位進行邏輯運算。按位進行邏輯運算的意義是:依次取被運算對象的每個位,進行邏輯運算,每個位的邏輯運算結果是結果值的每個位。c#支持的位邏輯運算符如表所示。

運算符號 意義 運算對象類型 運算結果類型 對象數 實例
~ 位邏輯運算,按位取反 整型,字符型 整型 1 ~a
& 位邏輯運算,其實與&&邏輯運算符有一致的地方 同上 同上 2 a & b
| 位邏輯運算,同樣與||有類似的地方 同上 同上 2 a | b
^ 位邏輯異或運算 同上 同上 2 a ^ b
<< 左移運算 同上 同上 2 a<<4
>> 右移運算 同上 同上 2 a>>2

2.1. ~:位邏輯非運算

位邏輯非運算是單目的,只有一個運算對象。位邏輯非運算按位對運算對象的值進行非運算,即:如果某一位等於0,就將其轉變為1;如果某一位等於1,就將其轉變為0。

比如,對二進位的10010001進行位邏輯非運算,結果等於01101110,用十進位表示就是:

145等於110;對二進位的01010101進行位邏輯非運算,結果等於10101010。用十進位表示就是85等於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;

這個是怎麼操作二進位的呢,首先要要記住一些原則:

原碼* 反碼 補碼** 取反
正數 符號位+絕對值 原碼 原碼 0、1對換
13 0 1101 0 1101 0 1101 1 0010
負數 符號位+絕對值 絕對值取反 反碼+1 0、1對換
-14 1 1110 1 0001 1 0010 0 1101

*:符號位的長度與類型定義有關,c#中int的符號位為1位 **:c#中數值以補碼存儲

以下展示兩者的原碼間如何轉換

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的源码

經過多次實驗得到一個規律就是:

~(+a)= -(a+1);(正數按位取反只需要把當前數加1然後改成負的)

~(-a)= (+a-1);(負數按位取反只需要把當前數先當做正數,然後減1得到結果)

2.2. $:位邏輯與運算

位邏輯與運算將兩個運算對象按位進行與運算。與運算的規則:1與1等於1,1與0等於0。

示例代碼:

int a = 13;
int b = 14;
int result = a & b;	// 12

轉換為二進位:

int a = 0000 1101;
int b = 0000 1110;
int result = 0000 1100;

&運算符會對二進位相同位置上面的0和1進行對比,當相同位置數字相同時就返回這個相同的數,否則就返回0,是不是和&&運算符判斷兩個bool 一致則返回true,否則返回false類似。所以我們得到了result這個結果,轉化成十進位就是12了。

2.3. |:位邏輯或運算

位邏輯或運算將兩個運算對象按位進行或運算。或運算的規則是:1或1等1,1或0等於1,

示例代碼:

int a = 13;
int b = 14;
int result = a | b;	// 15

轉換為二進位:

int a = 0000 1101;
int b = 0000 1110;
int result = 0000 1111;

其實判斷方式是一樣的,只是返回的結果不一樣,|運算符判斷兩個二進位相同位置的0和1,只要其中一個位置的數字是1就返回1,是不是和||運算符同樣很類似,只要一個true則返true,再把得到的結果轉化成10進位就是15了。

2.4. ^:位邏輯異或運算

位邏輯異或運算將兩個運算對象按位進行異或運算。異或運算的規則是:1異或1等於0,

1異或0等於1,0異或0等於0。即:相同得0,相異得1。

示例代碼:

int a = 13;
int b = 14;
int result = a ^ b;	// 3

轉換為二進位:

int a = 0000 1101;
int b = 0000 1110;
int result = 0000 0011;

從中可以看出,^ 判斷相同位置上面的數字時,如果兩個數相同,不論是0還是1都返回0,如果其中一個為1就返回1。而|是只要有一個只要位置上一個為1就返回1,所以名字叫異或(不同的返回或)。

2.5. <<:位左移運算

位左移运算将整个数按位左移若干位,左移后空出的部分0。比如:8位的byte型变量byte a=0x65(即二进制的01100101),将其左移3位:a<<3的结果是0x27(即二进制的00101000)。

byte a = 0110 0101;
a <<= 3;//0010 1000

將第一個操作數向左移動第二個操作數指定的位數,空出的位置補0。 左移相當於乘.左移一位相當於乘2;左移兩位相當於乘4;左移三位相當於乘8。

 x<<1= x*2 
 x<<2= x*4 
 x<<3= x*8 
 x<<4= x*16

2.6. >>:位右移運算

位右移运算将整个数按位右移若干位,右移后空出的部分填0。比如:8位的byte型变量byte a=0x65(既(二进制的01100101))将其右移3位:a>>3的结果是0x0c(二进制00001100)。

byte a = 0110 0101;
a >>= 3;//0000 1100

將第一個操作數向右移動第二個操作數所指定的位數,空出的位置補0。

右移相當於整除.右移一位相當於除以2; 右移兩位相當於除以4; 右移三位相當於除以8。

 x>>1= x/2 
 x>>2= x/4 
 x>>3= x/8 
 x>>4= x/16

3. 總結及問題答案

看微软文档位运算符和移位运算符两点注意

  1. 位运算和移位运算永远不会导致溢出,并且不会在已检查和未检查的上下文中产生相同的结果。
  2. 移位运算符仅针对 intuintlongulong 类型定义,因此运算的结果始终包含至少 32 位。如果左侧操作数是其他整数类型(sbytebyteshortushortchar),则其值将转换为 int 类型。

這裡給出文章開頭問題的答案及答案解析結束本文:

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位移后结果不同的原因:

  1. 對於有符號整數的右移操作,會將最高位的符號位也一同右移。這意味著如果原始數值的最高位是1,那麼右移後,符號位會被保留,即填充1。這種右移操作被稱為算術右移。
  2. 對於無符號整數的右移操作,不會保留符號位,而是將最高位的0也一同右移。這種右移操作被稱為邏輯右移。

本文如果有錯誤的地方歡迎指正,文中參考資料:

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 2026/2/7

aot使用經驗總結

從項目創建伊始,就應養成良好的習慣,即只要添加了新功能或使用了較新的語法,就及時進行 aot 發布測試。

继续阅读