當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > C語言運算符
一、前言
在嵌入式開發(fā)中,我們一般選用C語言作為開發(fā)語言。一個主要的原因在于C語言提供了大量的運算符,比如我們對硬件的操作一般涉及到對位的操作,而C語言就提供了這樣的運算符,這是其他語言不具備的。
二、C語言運算符有哪些
C語言有大量的運算符,可大致分為以下幾類:括號與結(jié)構(gòu)體符號、單目、算術(shù)、移位、關(guān)系、位、邏輯、三目、賦值、逗號。
括號與結(jié)構(gòu)體符號:括號包括()、[],結(jié)構(gòu)體符號指的是結(jié)構(gòu)體成員引用時的符號“->”、“.”,他們也是運算符,并且優(yōu)先級與括號相當(dāng),這也是我們把兩者放在一起討論的原因。至于如何使用則是結(jié)構(gòu)體的內(nèi)容。
單目運算符:單目運算符有很多,例如:!邏輯非、~按位取反、++自增、--自減、+正、-負(fù)、&求地址運算符、*間址運算符、sizeof()求所占字節(jié)數(shù)、(類型名)強制類型轉(zhuǎn)換。這些運算符的運算對象只有一個。其中&與*屬于指針內(nèi)容,我們不做細(xì)說。邏輯非我們在下面邏輯運算符時說明,按位取反我們在下面位運算符時說明,強制類型轉(zhuǎn)換我們在格式轉(zhuǎn)換時說明。Sizeof()首先不是函數(shù),用于求類型的所占字節(jié)數(shù)。例如:int a;sizeof(a)或sizeof(int)得到的值都是4,即整型占4個字節(jié)。()中可以是變量也可以是數(shù)據(jù)類型也可以是字符串常量。例如:char ch[20]=”hello”;我們定義字符數(shù)組來保存字符串,當(dāng)我們要求字符串長度時我們發(fā)現(xiàn)sizeof(ch)得到的大小為20,即數(shù)組的大小,那么怎么求字符串長度呢?我們可以用字符串的相關(guān)函數(shù)strlen(),但是也可以sizeof(“hello”);它的結(jié)果為6,即計算字符串最后的空字符’\0’。++與--是我們經(jīng)常用到的運算符,簡單來說,有以下四種情況:
a=10,a++ ++在a的后面,先把a的值賦值給表達(dá)式,a在自加1。即 a=10,b=a,a=a+1
a=10,++a ++在a的前面,a先自加1,再把a的值賦值給表達(dá)式。即 a=10,a=a+1,b=a
a=10,a-- --在a的后面,先把a的值賦值給表達(dá)式,a在自減1。即 a=10,b=a,a=a-1
a=10,--a --在a的前面,a先自減1,再把a的值賦值給表達(dá)式。即 a=10,a=a-1,b=a
上例中a++/++a/a--/--a代表表達(dá)式,我們可以理解為:b=a++/b=++a/b=a--/b=--a
算術(shù)運算符:+、-、*、/、%。需要注意的是,在做相乘運算時,*不能省略。/表示除號,%表示取余。例:10/3=3 10%3=1 這里%是取10除以3后的余數(shù),所以結(jié)果為1。要注意的是%左右兩邊必須都是整數(shù)。而10/3的結(jié)果為什么是3而不是3.3333呢?這里涉及到格式轉(zhuǎn)換的知識,是我們格式轉(zhuǎn)換部分要說的。
移位運算符:>> << 。移位運算符右移與左移是對位進行操作。例如:a=10,b=a>>1,
此例的意思是把數(shù)值a往右移動1位,把結(jié)果賦值給b。我們知道數(shù)據(jù)在內(nèi)存中以二進制存放,10對應(yīng)的二進制位1010,各位往右移一位得到0101,最右邊的0被移出去,左邊空的一位我們補0,所以b的值為0101,即5。這是右移,如果數(shù)據(jù)右邊有足夠多的0,我們可以往右移動多位,規(guī)律為往右移動移位相當(dāng)于除以2,移動兩位相當(dāng)于除以2^2,移動n位相當(dāng)于除以2^n.左移<<剛好相反,它是把數(shù)據(jù)按位往左移動,最右邊補0.例如:a=10,b=a<<2;
相當(dāng)于把1010往左移兩位變?yōu)?0 1000,即b的值為40.我們發(fā)現(xiàn)在數(shù)值上相當(dāng)于a*2^2。
所以我們的規(guī)律就是:往右移n位,相當(dāng)于除以2^n 。往左移n位,相當(dāng)于乘以2^n 。實際上我們就是用左移右移來代替乘除的,這樣不需要計算與賦值過程,只需要將各位移動,更加快捷。
關(guān)系運算符:>大于、<小于、>= 大于或等于、<=小于或等于、==等于、!=不等于。關(guān)系運算符用于比較大小,需要注意的是:1、關(guān)系運算符的寫法。當(dāng)要表示10<a<20時,應(yīng)該寫為a>10&&a<20。
&&是邏輯與運算符,表示并且。2、關(guān)系運算符的值是邏輯值。例如:a=10,b=20; a<b的值為1,既不是a的值也不是b的值。因為關(guān)系運算符的值是邏輯值,邏輯值只有兩個1,0。
如果關(guān)系成立,即邏輯為真,那么值就是1.如果關(guān)系不成立,即邏輯為假,那么值就是0.
邏輯運算符:&&邏輯與、||邏輯或、!邏輯非。邏輯運算符的值也是邏輯值,需要注意的是對數(shù)據(jù)來說非0為真,0為假。這三個運算符的關(guān)系為:
邏輯與:兩個數(shù)據(jù)全為真的時候結(jié)果才為真
1 1 1
1 0 0
0 1 0
0 0 0
邏輯或:兩個數(shù)據(jù)有一個為真結(jié)果就為真
1 1 1
1 0 1
0 1 1
0 0 0
邏輯非:!是單目運算符,非真為假,非假為真。!0結(jié)果是1,!-1結(jié)果是0,!1結(jié)果也是0
位運算符:按位與&、按位或、按位取反、按位異或^。這些運算符也是對位的操作與邏輯運算符要注意區(qū)分。例如:10&20。我們看做:讓各位進行相與
01010
& 1 0100
00000
那么10&20的結(jié)果就是0。
與或關(guān)系我們都知道,在補充一下異或關(guān)系,相同為假,不同為真。
1 1 0
1 0 1
0 1 1
0 0 0
我們知道這些都是對位的操作,我們要額外說一下按位取反。例如:int a=1;~a的值為什么呢?我們打印之后發(fā)現(xiàn)結(jié)果為-2。這涉及到數(shù)據(jù)存放的知識。我們要知道數(shù)據(jù)以補碼形式存放、補碼形式打印。a的二進制,0000 0001,是一個正數(shù),它的補碼為它本身0000 0001,這里我們只以一個字節(jié)為例。當(dāng)我們~a后按各位取反,得到1111 1110,當(dāng)我們打印這個數(shù)據(jù)時,需要補碼打印,這時候它的最高位為1,表示負(fù)數(shù),負(fù)數(shù)的補碼為它的反碼加一。即:
1000 0001+1 = 1000 0010 對應(yīng)的十進制為-2。
三目運算符:?:。它是條件語句的內(nèi)容,C語言中只有這一個三目運算符,即運算對象有三個。例如:a=10,b=20,a>b?a:b的值為b的值。即a大于b為真時a的值是表達(dá)式的值,否則b的值是表達(dá)式的值。
賦值運算符:=、+=、-=、*=、/=、%=、&=、^=、!=、<<=、>>=。即上面的符號與=相結(jié)合。=叫賦值號,使用時要注意,例如:int a=10,表示把數(shù)據(jù)10賦值給整型變量a。a+=b表示a=a+b,其他符號用法相同。
逗號運算符:“,”。例如:a=(b+c,c+d,d+e);a的值為d+e的值,即最后一個表達(dá)式的值。所以逗號表達(dá)式的值為最后一個式子的值。但這并不表示前面的式子沒用,例如:a=(b++,c+d,b+d);我們要從左向右計算,因為b++改變了b的值,所以要先b++,在b+d。
三、運算符優(yōu)先級
我們在做簡單的符合運算時,比如:a+b/c+d 我們是先讓b/c,在讓三者進行相加。這里/號比加減運算優(yōu)先級要高。同理,當(dāng)我們的式子包含了以上運算符時,我們就要理清先算誰再算誰。這里我們已經(jīng)將運算符的優(yōu)先級整理為一句話:優(yōu)先級從高到低依次為:
() 單目算術(shù) 移位 關(guān)系 位 邏輯 三目 賦值 逗號
四、運算符結(jié)合性
這里討論的情況是當(dāng)式子中幾個運算符優(yōu)先級相同時,應(yīng)該先算誰再算誰。例如:*p++,我們知道*與++都是單目運算符,這時候先算哪個呢?我們也給大家總結(jié)了一句話:
單目、三目、賦值運算符結(jié)合性自右向左,其他運算符結(jié)合性自左向右。
我們給了如下三個例子:
Int a=10,int *p=&a,求*p++。根據(jù)結(jié)合性自右向左,應(yīng)該先算p++,即p指向a上面的那塊空間。所以*p++表示a上面那塊空間的值。
a>b?a>c?a:c:b>c?b:c; 這個式子表示的是求三個數(shù)最大值。根據(jù)結(jié)合性自右向左,先算b>c?b:c求b和c的最大值,在算a>c?a:c求a和c的最大值。最后比較a與b的值。
a=b+c=a+b;這種寫法是錯誤的,因為他的結(jié)合性自右向左,且+優(yōu)先級比=高,所以是先把a+b的值賦值給b+c,我們無法把一個值賦值給表達(dá)式,即賦值號左邊不能為式子。
五、格式轉(zhuǎn)換規(guī)則
1、運算符左右兩邊類型相同時,得到的結(jié)果也是這個類型。例:1/2=0,10/3=3
2、運算符左右兩邊類型不同時,先把他們往精確度更高的一側(cè)轉(zhuǎn)換,變?yōu)橄嗤念愋汀?例:1.0/2=0.5,10/3.0=3.333333
3、賦值號右面的數(shù)據(jù)會自動轉(zhuǎn)換為左面的數(shù)據(jù)類型。例:int a=2.678。a的值為2
4、我們可以對數(shù)據(jù)進行強制類型轉(zhuǎn)換。例:float a=2.789,(int)(a);a的類型變?yōu)閕nt,值為2