一、算術(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;
}

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)是沒有問題的。