C語言學習第8篇---位運算子使用探究

CodeAllen的部落格發表於2017-12-19

知識來源主要是陳正衝老師的《C語言深度解剖》及Delphi Tang老師的《C語言剖析》,有興趣的朋友可以看我置頂文章獲取

 

很多新手都對位運算子理解的都不是很深刻,但是位運算在實際程式設計中使用的卻很普遍,因為位運算是直接對bit的操作,效率最高。

 

與 &

  1. 計算
  2. 取特定位

 

或 |

1.計算

2.要將某幾位置一,就用與這幾位是1的書進行  或


取反 ~

1.按位取反(變成二進位制取反)


異或  ^

兩個數不同時為1,否則為0 

1.使特定的位翻轉,要將後七位翻轉,就與後七位是1的數異或

2.在不使用臨時變數的情況下實現倆個變數的互換

3.經常用在簡單的加密演算法上

 


左移  <<  雙目運算子

左運算元必須為整型

  char 和 short 被隱式轉換為int後進行移位操作

右運算元的範圍必須為 :【0,31】

左移運算子<<將運算子的二進位制位左移

  規則:高位丟棄,低位補0

右移運算子>>把運算子的二進位制位右移

  規則:高位補符號位,低位丟棄

 

 

迴圈移位:

left(unsigned value, int n)                                    /*自定義左移函式*/

{

    unsigned z;

    z = (value >> (32-n)) | (value << n);                        /*迴圈左移的實現過程*/

    return z;

}

迴圈右移

right(unsigned value, int n)                                    /*自定義右移函式*/

{

    unsigned z;

    z = (value << (32-n)) | (value >> n);                        /*迴圈右移的實現過程*/

    return z;

}

 

位運算

#include <stdio.h>
int main()
{
    printf("%d\n", 3 << 2);
    printf("%d\n", 3 >> 1);
    printf("%d\n", -1 >> 1);
    printf("%d\n", 0x01 << 2 + 3);
   
    printf("%d\n", 3 << -1); // oops!
   
    return 0;
}

 

小提示:

防錯的方法:

 ~避免位運算子,邏輯運算子和數學運算子同時出現在一個表示式中

  ~當位運算子,邏輯運算子合數學運算子需要同時參與運算子時,儘量使用括號()來表達計算次序

 

小技巧:

左移n位相當於乘以2的n次方,但效率比數學運算子高

右移n位相當於除以2的n次方,但效率比數學運算子高

 

實驗2:交換兩個整型變數的值

#include <stdio.h>
#define SWAP1(a, b)    \
{                      \
    int t = a;         \
    a = b;             \
    b = t;             \
}
#define SWAP2(a, b)    \
{                      \
    a = a + b;         \
    b = a - b;         \
    a = a - b;         \
}
#define SWAP3(a, b)    \
{                      \
    a = a ^ b;         \
    b = a ^ b;         \
    a = a ^ b;         \
}
int main()
{
    int a = 1;
    int b = 2;
   
   
    printf("a = %d\n", a);
    printf("b = %d\n", b);
   
    SWAP3(a ,b);
   
    printf("a = %d\n", a);
    printf("b = %d\n", b);
   
    return 0;
}

 

實驗三:混淆概念的判斷條件

#include <stdio.h>
int main()
{
    int i = 0;
    int j = 0;
    int k = 0;
   
    if( ++i | ++j & ++k )
    {
        printf("Run here...\n");
    }
   
    return 0;
}

 

位段

位段型別是一種特殊的結構型別,其所有成員的長度均是以二進位制位為單位定義的,結構中的成員被稱為位段。位段定義的一般形式為:

 

結構 結構名

{

 型別 變數名1:長度;

 型別 變數名2:長度;

 ……

 型別 變數名n:長度;

}

 

  一個位段必須被說明是int、unsigned或signed中的一種



迴圈移動例子:

#include <stdio.h>

left(unsigned value, int n)                                    /*自定義左移函式*/

{

    unsigned z;

    z = (value >> (32-n)) | (value << n);                        /*迴圈左移的實現過程*/ 

   return z;

}

right(unsigned value, int n)                                    /*自定義右移函式*/

{

    unsigned z;

    z = (value << (32-n)) | (value >> n);                        /*迴圈右移的實現過程*/

    return z;

}

main()

{

    unsigned a;

    int n;

    printf("please input a number:\n");

    scanf("%o", &a);                                        /*輸入一個八進位制數*/

    printf("please input the number of displacement(>0):\n");

    scanf("%d", &n);                                    /*輸入要移位的位數*/

    printf("the result is %o:\n", left(a, n));                    /*將左移後的結果輸出*/

    printf("the result is %o:\n", right(a, n));                    /*將右移後的結果輸出*/

}

 

 

 

運算子總結:

算數運算子:

+   -   *   /    %(取餘數)

 

 

關係運算子

>     >=    <      <=      !=(不等於)        =(等於)

 

 

邏輯運算子

!       &&(並且)      ||(或)

 

 

C語言對真假判斷:非零是真

                                零是假

 

&&左邊的表示式為假,右邊的肯定是不會執行的

||   左邊的表示式為真   ,右邊的表示式肯定不會執行

 

賦值運算子:

=      +=       *=             /=           -=

 

優先順序別:    算數>關係>邏輯>賦值

 

 

相關文章