操作符分類
- 算術(shù)操作符
- 移位操作符
- 位操作符
- 賦值操作符
- 單目操作符
- 關(guān)系操作符
- 邏輯操作符
- 條件操作符
- 逗號(hào)操作符
- 下標(biāo)引用、函數(shù)調(diào)用和結(jié)構(gòu)成員操作符
算術(shù)操作符
-
除了 % 操作符之外,其他的幾個(gè)操作符可以作用于整數(shù)和浮點(diǎn)數(shù)。
-
對(duì)于 / 操作符如果兩個(gè)操作數(shù)都為整數(shù),執(zhí)行整數(shù)除法。而只要有浮點(diǎn)數(shù)執(zhí)行的就是浮點(diǎn)數(shù)除法。
-
% 操作符的兩個(gè)操作數(shù)必須為整數(shù)。返回的是整除之后的余數(shù)。
移位操作符
請(qǐng)注意:移位操作符移動(dòng)的是二進(jìn)制位的補(bǔ)碼。
?:移位操作符的操作數(shù)只能是整數(shù),不要移動(dòng)負(fù)數(shù)位,這個(gè)是標(biāo)準(zhǔn)未定義的。
int num = 10;
num>>-1; //error
左移操作符
移位規(guī)則:左邊拋棄、右邊補(bǔ)0。并且被操作數(shù)在沒(méi)有被重新賦值的情況下,自身的值并不會(huì)被 << 操作符影響。
右移操作符
右移運(yùn)算有兩種規(guī)則:
- 算術(shù)右移: 右邊丟棄、左邊補(bǔ)原來(lái)的符號(hào)位。
- 邏輯右移:右邊丟棄、左邊補(bǔ)0。
但就目前來(lái)看大多數(shù)情況下都是算術(shù)右移。
位操作符
請(qǐng)注意:這里的位指的是二進(jìn)制位,且操作數(shù)必須是整數(shù)。
- &:對(duì)應(yīng)的二進(jìn)制位上有0,按位與的結(jié)果就為0。
- | :對(duì)應(yīng)的二進(jìn)制位上有1,按位或的結(jié)果就為1。
- ^ :對(duì)應(yīng)的二進(jìn)制位相同為0,相異為1。
賦值操作符
賦值操作符支持連續(xù)賦值,雖然VS編譯器支持給變量連續(xù)賦值,但為了代碼清晰爽朗,還是推薦大家一步一步進(jìn)行賦值。
復(fù)合賦值符
單目操作符
單目操作符介紹
- 邏輯反操作符:?。?!常被用來(lái)調(diào)整判斷條件。)
- 取地址操作符:& 和 解引用操作符:* (& 常被用來(lái)獲取變量和數(shù)組的地址。)
- 按位取反操作符:~ (~ 將二進(jìn)制位按位取反,包括符號(hào)位。)
按位取反后,請(qǐng)注意符號(hào)位的值:
- 若為1:說(shuō)明按位取反后是個(gè)負(fù)數(shù)繼續(xù)補(bǔ)碼轉(zhuǎn)換為原碼。
- 若為0:說(shuō)明按位取反后是個(gè)正數(shù),補(bǔ)碼即原碼。
- 前置++和后置++
-
后置++:先對(duì)a先使用,再增加。
-
前置++:先對(duì)a進(jìn)行自增,然后再使用。
- 強(qiáng)制類型轉(zhuǎn)換操作符:(類型) (強(qiáng)制類型轉(zhuǎn)換只是將變量的類型臨時(shí)改變成了所需要的類型的值,對(duì)變量來(lái)說(shuō)并不是真的改變了它的類型)
sizeof 和 數(shù)組
- sizeof 可以求 變量/類型 所占空間的大小。
- sizeof 后是類型,類型旁邊的括號(hào)不能省略;sizeof后面是變量名,括號(hào)可以省略。
- sizeof 可以計(jì)算數(shù)組的大小
關(guān)系操作符
? 特別小心==和=的使用,前期寫代碼我總是在這里出錯(cuò)
邏輯操作符
這里注意區(qū)分&&(邏輯與)、&(按位與)、| |(邏輯或)和 |(按位或)。
- 邏輯與操作符(&&)左右兩端表達(dá)式結(jié)果都為真,算出的結(jié)果就為真。
- 邏輯或操作符(| |)左右兩端表達(dá)式結(jié)果都為假,算出的結(jié)果才為假。
條件操作符
使用方法:先判斷表達(dá)式1的結(jié)果是否為真,如果表達(dá)式1的結(jié)果為真,那下一步就算表達(dá)式的結(jié)果并將其作為整個(gè)條件表達(dá)式的值;如果表達(dá)式1的結(jié)果為假,那下一步就算表達(dá)式3的結(jié)果并將其作為整個(gè)條件表達(dá)式的值。
逗號(hào)操作符
逗號(hào)表達(dá)式:就是用逗號(hào)隔開(kāi)的多個(gè)表達(dá)式,從左向右依次執(zhí)行。整個(gè)表達(dá)式的結(jié)果是最后一個(gè)表達(dá)式的結(jié)果。
下標(biāo)引用、函數(shù)調(diào)用和結(jié)構(gòu)成員操作符
- 下標(biāo)引用操作符:[ ] ( [ ] 有兩個(gè)操作數(shù):一個(gè)數(shù)組名 + 一個(gè)索引值 )
- 函數(shù)調(diào)用操作符:() (()接受一個(gè)或者多個(gè)操作數(shù):第一個(gè)操作數(shù)是函數(shù)名,剩余的操作數(shù)就是傳遞給函數(shù)的參數(shù) )
- 結(jié)構(gòu)體成員訪問(wèn)操作符: . 和 -> ( 結(jié)構(gòu)體變量 . 結(jié)構(gòu)體成員名, 結(jié)構(gòu)體變量的地址 -> 結(jié)構(gòu)體成員名 )
表達(dá)式求值
表達(dá)式求值的順序一部分是由操作符的優(yōu)先級(jí)和結(jié)合性決定。同樣,有些表達(dá)式的操作數(shù)在求值的過(guò)程中可能需要轉(zhuǎn)換為其他類型。
- 數(shù)據(jù)類型小于int類型時(shí)進(jìn)行隱式類型轉(zhuǎn)換。
- 數(shù)據(jù)類型大于等于int類型時(shí)進(jìn)行算術(shù)轉(zhuǎn)換。
隱式類型轉(zhuǎn)換
C 的整型算術(shù)運(yùn)算總是至少以缺省整型(int)類型的精度來(lái)進(jìn)行的。為了獲得這個(gè)精度,表達(dá)式中的字符(char)和短整型(short )操作數(shù)在使用之前被轉(zhuǎn)換為普通整型,這種轉(zhuǎn)換稱為整型提升。
整型提升的意義(為什么要進(jìn)行整型提升):
截?cái)嗪驼吞嵘?/strong>
整形提升是按照變量的數(shù)據(jù)類型的符號(hào)位來(lái)提升的。( 無(wú)符號(hào)整形提升,高位補(bǔ)0 )
- 負(fù)數(shù)的整形提升:高位補(bǔ)充其符號(hào)位 1 。
- 正數(shù)的整形提升:高位補(bǔ)充其符號(hào)位 0 。
幾個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明截?cái)嗪驼吞嵘?/p>
整型提升是隱式,不經(jīng)意間發(fā)生的,就好像從來(lái)都沒(méi)有感知到它的存在一樣,但確是的的確確存在的。
上個(gè)例子中的c只要參與表達(dá)式運(yùn)算,就會(huì)發(fā)生整形提升,+c是個(gè)表達(dá)式 ,就會(huì)發(fā)生提升,所以sizeof(+c) 是4個(gè)字節(jié)。表達(dá)式 -c 也會(huì)發(fā)生整形提升,所以 sizeof(-c) 是4個(gè)字節(jié),但是 sizeof( c )就是1個(gè)字節(jié)。
算數(shù)轉(zhuǎn)換
如果某個(gè)操作符的各個(gè)操作數(shù)屬于不同的類型,那么除非其中一個(gè)操作數(shù)的轉(zhuǎn)換為另一個(gè)操作數(shù)的類型,否則操作就無(wú)法進(jìn)行。下面的層次體系稱為尋常算術(shù)轉(zhuǎn)換,如果某個(gè)操作數(shù)的類型在下面這個(gè)列表中排名較低,那么首先要轉(zhuǎn)換為另外一個(gè)操作數(shù)的類型后執(zhí)行運(yùn)算。
- long double
- double
- float
- unsigned long int
- long int
- unsigned int
- int
操作符屬性
復(fù)雜表達(dá)式的求值有三個(gè)影響的因素。
- 操作符的優(yōu)先級(jí)
- 操作符的結(jié)合性
- 是否控制求值順序。
兩個(gè)相鄰的操作符執(zhí)行的先后順序取決于他們的優(yōu)先級(jí)。如果兩者的優(yōu)先級(jí)相同,取決于他們的結(jié)合性。
一些代碼問(wèn)題
代碼1:
a*b + c*d + e*f
代碼1在計(jì)算的時(shí)候,由于 * 比+的優(yōu)先級(jí)高,只能保證 * 的計(jì)算是比+早,但是優(yōu)先級(jí)并不能決定第三個(gè) * 比第一個(gè)+早執(zhí)行。
代碼2:
c + --c;
雖然這個(gè)代碼的操作順序可以確定且有且僅有一種:操作符的優(yōu)先級(jí)只能決定自減–的運(yùn)算在+的運(yùn)算的前面。但是我們并沒(méi)有辦法得知,+操作符的左操作數(shù)的獲取在右操作數(shù)之前還是之后求值,所以結(jié)果是不可預(yù)測(cè)的,是有歧義的。
代碼3:
int main()
{
int i = 10;
i = i-- - --i * ( i = -3 ) * i++ + ++i;
printf("i = %d\n", i);
return 0;
}
注意:不要寫出非常復(fù)雜的表達(dá)式代碼。
代碼4:
int fun()
{
static int count = 1;
return ++count;
}
int main()
{
int answer;
answer = fun() - fun() * fun();
printf( "%d\n", answer);
return 0;
}
雖然該代碼在大多數(shù)的編譯器上求得結(jié)果都是相同的。但是還是存在一些問(wèn)題經(jīng)不起推敲:操作符的優(yōu)先級(jí)只能決定 * 比 - 先算,但無(wú)法決定表達(dá)式中的3個(gè)函數(shù)先調(diào)用哪個(gè)。
代碼5:
#include <stdio.h>
int main()
{
int i = 1;
int ret = (++i) + (++i) + (++i);
printf("%d\n", ret);
return 0;
}
簡(jiǎn)單看一下匯編代碼后發(fā)現(xiàn)。這段代碼中的第一個(gè) + 在執(zhí)行的時(shí)候,第三個(gè)++是否執(zhí)行,這個(gè)是不確定的,因?yàn)橐揽坎僮鞣膬?yōu)先級(jí)和結(jié)合性是無(wú)法決定第一個(gè) + 和第三個(gè)前置 ++ 的先后順序。
總結(jié):我們寫出的表達(dá)式如果不能通過(guò)操作符的屬性確定唯一的計(jì)算路徑,那這個(gè)表達(dá)式就是存在問(wèn)題的。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-793972.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-793972.html
到了這里,關(guān)于【C語(yǔ)言】操作符的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!