運(yùn)算符(C語言)

一、算術(shù)運(yùn)算

1、*、/

+-,CPU在一個(gè)周期內(nèi)可以處理完。

*/在大多數(shù)CPU中都是不支持的。
它們可能需要CPU多個(gè)周期才能完成,甚至要利用軟件的模擬方法去實(shí)現(xiàn)。

在arm開發(fā)中,*/很可能會(huì)被編譯器編輯為軟件浮點(diǎn)方法。如果是裸機(jī)開發(fā),就實(shí)現(xiàn)不了,必須借助第三方乘法庫/除法庫來實(shí)現(xiàn)。

如果CPU不支持*/,會(huì)導(dǎo)致程序的可移植性變差。

2、%

0%3 = 0   
1%3 = 1 
2%3 = 2  
3%3 = 0  
4%3 = 1 
... ...

應(yīng)用場(chǎng)景:

  • 取一個(gè)范圍的數(shù)
    例如:給一個(gè)任意的數(shù)字m,得到一個(gè)1到100以內(nèi)的數(shù)字?

    (m % 100)+1 
    
  • M進(jìn)制的數(shù)

  • 循環(huán)數(shù)據(jù)結(jié)構(gòu)的下標(biāo)


二、邏輯運(yùn)算

1、&&、||

// 001.c
#include <stdio.h>
int main()
{
    int a = 10;
    int res = 0;
    res = ((a == 10) || printf("======\n"));
    printf("res is %d\n", res);
    return 0;
}
|| 左邊的值為真,則不判斷右邊的值
// 002.c
#include <stdio.h>
int main()
{
    int a = 10;
    int res = 0;
    res = ((a != 10) || printf("======\n"));
    printf("res is %d\n", res);
    return 0;
}
|| 左邊的值為假時(shí),才判斷右邊的值

2、!

邏輯運(yùn)算的!和位運(yùn)算的~區(qū)別

int a = 0x0;
!a : 真
~a :0xffff

三、位運(yùn)算

C語言中最接近底層和硬件開發(fā)的一種運(yùn)算。
對(duì)嵌入式工程師,應(yīng)用頻率非常高。

1、移位:<<(左移)、>>(右移)

<<(左移):左移1位,相當(dāng)于2*
m<<n:m*2^n

4 ——  0100
8 ——  1000

int a = b*32 ——> int a = b<<5   // C語言會(huì)將b*32轉(zhuǎn)化為b<<5,這樣CPU在一個(gè)周期內(nèi)就可以處理完了

-1 * 2 = -2
8bit舉例:
-1:
原碼:1 0 0 0 0 0 0 1
反碼:1 1 1 1 1 1 1 0
補(bǔ)碼:1 1 1 1 1 1 1 1    // -1在計(jì)算機(jī)中全是高電平

-2:
原碼:1 0 0 0 0 0 1 0
反碼:1 1 1 1 1 1 0 1
補(bǔ)碼:1 1 1 1 1 1 1 0
// -1左移1位,最后面一位就空了,就用0補(bǔ)位。
// 可看出,-2是-1左移一位得到的

>>(右移):右移1位,相當(dāng)于/2
m>>n :m/2^n

// 右移與正負(fù)符號(hào)有關(guān)
int a;  a>>n
unsigned int a;  a>>n
// 這兩種情況CPU表現(xiàn)形式是不一樣的

右移時(shí),如果是負(fù)數(shù),則最左邊補(bǔ)1; 如果是正數(shù),最左邊補(bǔ)0。

/*003.c*/
#include <stdio.h>
int main()
{
    int a = 10;
    while(a) 
    {
        a = a>>1;   // 當(dāng)a全0時(shí),就不再循環(huán)
    }
    printf("++++++++++\n");
}
/*004.c*/
#include <stdio.h>
int main()
{
    int a = -10;
    while(a) 
    {
        a = a>>1;   // 因?yàn)閍為負(fù)數(shù),首位永遠(yuǎn)是1,因此a永遠(yuǎn)無法為0,該循環(huán)為死循環(huán)
    }
    printf("++++++++++\n");
}

2、&(逐位與)、|(逐位或)

(1)&的應(yīng)用場(chǎng)景:

  • 屏蔽

    A & 0 —— 0 
    int a = 0x1234;
    a & 0xff00;    // 屏蔽低8位(bit),取出了高8bit
    

硬件中,&也叫清零器(clear)

  • 取出

    A & 1 —— A
    

(2)|的應(yīng)用場(chǎng)景:

  • 設(shè)置為高電平

    A | 1 —— 1
    

硬件中,|也叫設(shè)置器(set)

  • 保留

    A | 0 —— A
    

例1:設(shè)置一個(gè)資源的bit5為高電平,其它位不變。

int a;
a = a | 100000   // 末尾一位是bit0,倒數(shù)第2位為bit1 ...

a = a | (0x1<<5)

a | (0x1<<n):將a的第n位設(shè)置為高電平。

例2:清除第5位。

int a;

a = a & 0 1 1 1 1 1   // 這個(gè)寫法是錯(cuò)誤的,因?yàn)楦呶粸?,會(huì)把a(bǔ)的高位也同時(shí)都清零;而且,如果移植到別的平臺(tái),前面的0更多的話,把把更多位清零。

a = a & (~(0x1<<5))   // 只有第5位為0,其它位全為1

a & (~(0x1<<n)):清除a的第n位。

例3:某幾位設(shè)置為某個(gè)數(shù)。
如,想設(shè)置4、5、6bit為101,該怎么處理?

3、^(異或)

1 ^ 1 = 0
0 ^ 0 = 0
1 ^ 0 = 1

硬件上用的不多,主要用在算法上。在設(shè)計(jì)的數(shù)學(xué)算法上,會(huì)用到^進(jìn)行加密、解密(AES、SHA1等)。

例:兩數(shù)交換。

int a = 20;
int b = 30;

// 方法1:引入中間變量。
int c;
c = a;
a = b;
b =c;

// 方法2:不引入中間變量。
a = a ^ b;
b = a ^ b;
a = a ^ b;

4、~(逐位取反)

~0xf0 (32位常量):  0xffff ff0f

四、內(nèi)存訪問符號(hào)

對(duì)于連續(xù)空間中不同成員變量的訪問方法:
->:地址訪問。
.:變量訪問。

&p:取地址。
*p:指針。


五、邏輯結(jié)構(gòu)

switch里面必須用整型數(shù)字,不能用浮點(diǎn)數(shù)。

內(nèi)核編程中,有的場(chǎng)景不得不用goto。
一定要保證goto不能在不同函數(shù)間跳,在同一函數(shù)內(nèi)是沒有問題的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容