溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C之位運算(十五)

發(fā)布時間:2020-07-22 06:02:29 來源:網(wǎng)絡 閱讀:2190 作者:上帝之子521 欄目:編程語言

        我們在嵌入式的開發(fā)中難免會遇到 C 語言中的位運算符,因為我們需要效率,而位運算恰好效率比別的運算符效率高多了。位運算符直接對 bit 為進行操作,其效率最高。常見的位運算操作如下

C之位運算(十五)

        我們在左移和右移時必須要注意:1、左操作數(shù)必須為整數(shù)類型,char 和 short 被隱式轉(zhuǎn)換為 int 后進行移位操作;2、右操作數(shù)的范圍必須為:[0,31];3、左移運算符 << 將運算數(shù)的二進制位左移,規(guī)則是高位丟棄低位補0;4、右移運算符 >> 把運算數(shù)的二進制位右移,規(guī)則是高位補符號位低位丟棄。

        比如 0x1 << 2 + 3 的值會是多少呢?我們猜想有這么幾種情況:1、先算 0x1 << 2 再把中間結(jié)果加 3,最終結(jié)果為 7;2、先算 2 + 3,所以結(jié)果為 32;3、這么混合的運算會出錯。我們來看個示例代碼,來看看編譯器是如何處理的,代碼如下:

#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);
    
    return 0;
}

        我們先來分析下這個代碼,第5行 3 << 2 ==> 11 << 2 ==> 1100 ==> 12;第6行 3 >> 1 ==> 11 >> 1 ==> 1;編譯后結(jié)果如下:

C之位運算(十五)

        我們可以看到我們的分析是對的,第8行執(zhí)行的是我們之前分析的第2種結(jié)果。

        我們在 C 語言中應避免位運算符、邏輯運算符和數(shù)學運算符同時出現(xiàn)在一個表達式中;但位運算符、邏輯運算符和數(shù)學運算符需要同時參與運算時,盡量使用括號()來表達計算次序;左移 n 為相當于乘以 2 的 n 次方(同理右移相當于除),但效率比數(shù)學運算符高。

        我們下來看個實現(xiàn)宏函數(shù)交換的功能,這也是筆試中經(jīng)常會遇到的一個題目,代碼如下:

#define SWAP1(a, b)    \
{                      \
    int t = a;         \
    a = b;             \
    b = t;             \
}

        這是我們最常用的一種寫法,但是它需要一個額外變量。我們下面來看個不需要借助額外變量的版本就可以完成的宏函數(shù),代碼如下:

#define SWAP2(a, b)    \
{                      \
    a = a + b;         \
    b = a - b;         \
    a = a - b;         \
}

        第4 行相當于 b = (a + b) - b ==> b = a;第5行相當于 a = (a + b) - b ==> a = (a + b) - a ==> a = b;這種也可以完成交換功能,但是它的效率似乎不是那么的高,因為要借助于數(shù)學運算。我們再來實現(xiàn)一個基于位運算實現(xiàn)的,代碼如下:

#define SWAP3(a, b)    \
{                      \
    a = a ^ b;         \
    b = a ^ b;         \
    a = a ^ b;         \
}

        我們上面的代碼效率是非常高的,我們來分析下,第 4 行相當于 b = (a ^ b) ^ b ==> b = a; 第5行相當于 a = (a ^ b) ^ b ==> a = (a ^ b) ^ a ==> a = b;這樣也實現(xiàn)了交換的功能。

        位運算與邏輯運算不同之處:1、位運算沒有短路規(guī)則,每個操作數(shù)都參與運算;2、位運算的結(jié)果為整數(shù),而不是 0 或 1;3、位運算的優(yōu)先級高于邏輯運算優(yōu)先級。

        我們來看看下面這個示例代碼:

#include <stdio.h>

int main()
{
    int i = 0;
    int j = 0;
    int k = 0;
    
    if( ++i | ++j & ++k )
    {
        printf("Run here...\n");
    }
    
    printf("i = %d\n", i);
    printf("j = %d\n", j);
    printf("k = %d\n", k);
    
    return 0;
}

        我們分析下,第 9 行執(zhí)行完,i、j、k分別就是1了。因為我們這塊是位運算,所以沒有短路規(guī)則。我們來看看編譯結(jié)果:

C之位運算(十五)

        是如我們分析的那樣,如果我們第9行換成if( ++i || ++j && ++k ) 這樣,那么便是 i = 1,j = 0, k = 0 了,打印如下

C之位運算(十五)

        通過我們今天學習的位運算符,總結(jié)如下:1、位運算符只能用于整數(shù)類型;2、左移和右移運算符的右操作數(shù)范圍必須為[0, 31];3、位運算沒有短路規(guī)則,所有操作數(shù)均會求值;4、位運算的效率高于四則運算和邏輯運算;5、運算優(yōu)先級:四則運算 > 位運算 > 邏輯運算。后面我們會繼續(xù)對 C 語言的學習。


         歡迎大家一起來學習 C 語言,可以加我QQ:243343083

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI