詳細介紹了C語言表達式、算術運算符、賦值運算符、關系運算符、條件結構、邏輯運算符、位運算符的語法和使用方法,并討論了運算符的優先級。
1、表達式與算術運算符
在C語言中,表達式是一個類似數學中的算式,表達式由變量、字面值、常量、運算符號構成。表達式的計算結果是一個值,值的類型可以數值,也可以是邏輯值。
【 例3-1 】 計算存款一年本金利息和的表達式
deposit*(1+rate)
在上面的表達式中,deposit是存儲存款額度的變量,rate是存儲銀行年利率的變量,數字1是字面值,符號“*”是乘法運算符,表達式中的括號和數學四則運算的括號意義相同,用于提高括號內子表達式的運算優先級。
觀察發現,1+rate也是一個表達式,它符合表達式的定義,在當前表達式中,該表達式為子表達式,因此一個復雜的表達式由多個子表達式構成。
在C語言中,表達式中的運算符號稱為運算符,運算符作用的變量、常量、字面值、子表達式稱為操作數。例如:運算符號“*”兩邊的操作數為變量deposit和子表達式(1+rate);運算符號“+”兩邊的操作數為字面值1和變量rate。
運算符若需要N個操作數參與運算,則稱為N目運算符。例如:加法、乘法、除法等運算符都需要兩個操作數參與運算,稱為雙目運算符;自增、自減運算符需要單個操作數參與運算,稱為單目運算符。
表達式左側一般是待賦值的變量,該表達式返回的結果為浮點類型,計算結果賦值給表達式左側的變量。
例如:
total = deposit*(1+rate)
表達式的計算結果賦值給變量total。
【 例3-1 】表達式的運算符在運算類型屬于算術運算符,其作用和數學中的運算符相同,下表列出了C語言支持的算術運算符。
表中的加、減、乘、除運算符比較容易理解和掌握,下面重點介紹取余、自增、自減運算符。
取余運算符
取余運算符是雙目運算符,需要兩個操作數??梢杂脕碛嬎銉蓚€數之間的余數,它可以用在整數和浮點數之間,但是最終結果只能是整數。運算結果是運算符左邊的操作數除以運算符右邊的操作數后所得的余數。
假設 a % b =c(余數為d),其中a和b均為整數,則余數d為a % b的結果。
取余運算符可以解決一些簡單的數學問題。例如:可以使用取余運算符來檢查一個數是否為偶數,如果一個數除以2的余數是0,那么它就是偶數;也可以用來檢查一個數是否是3的倍數,如果一個數除以3的余數是0,那么它就是3的倍數。
自增自減運算符
自增自減是單目運算符,只需要一個操作數參加運算。自增和自減從字面上理解就是自身增加或減少,增加或減少多少呢?自增是自身做加1操作,自減是自身做減1操作。在c語言中,并不是所有變量都可以使用自增自減操作符;可以使用自增自減操作符的數據類型有:int、float、double 、char、long。
自增(++):將變量的值加1,分前綴式(如++a)和后綴式(如a++)。前綴式是先加1再使用;后綴式是先使用再加1。
例如:
int count=10;
printf("count=%d",count++);
上述程序段執行后,輸出結果是10還是11呢?count++是后綴式,后綴式是先使用再加1,因此先輸出count的當前數值,然后count再做加1操作,輸出結果是10。
int count=10;
printf("count=%d",++count);
上述程序段執行后,輸出結果是11。因為++count是前綴式,前綴式是變量先自增再使用,變量count先做加1操作,然后再輸出變量count的值。
自減(--):將變量的值減1,也分前綴式(如--a)和后綴式(如a--)。前綴式是先減1再使用;后綴式是先使用再減1。
2、賦值運算符
我們回顧一下數學運算符號“=”,在數學中該符號是表示相等的符號,讀作“等于”。等號表示兩端的數字、算式是相等的。如:2+3=5,就是表示等號左邊的2加上3與右邊的5是相等的,7-2=2+3表示左右兩邊算式相等。
在C語言中,也用到了符號“=”,不過和數學中的等號意義完全不同,C語言中的“=”是賦值的意思,該符號是賦值運算符,它是一個雙目運算符,它的作用是將右側的值賦值給左側的變量。
例如:
int a,b;a = 30;b = a+20;
上述代碼執行后,a的值為30,b的值為50。賦值運算符“=”左側的操作數必須是變量,右側的操作數可以字面值、變量、常量或表達式,若賦值運算符右邊的操作數為表達式,編譯器會先計算表達式的值,然后再將值賦值給運算符左側的變量。
可以在聲明變量時為變量賦值:
int a=30,b=a+20;
上面的語句在定義變量b時用到了變量a,因為變量a在變量b之前已被定義,因此上面的語句是合法的。
為了簡化計算,C語言還提供了復合賦值運算符,復合賦值運算符是賦值運算符和算術運算符合并成一個新的運算符,該運算符稱為復合賦值運算符。使用復合賦值運算符時,被賦值的變量首先使用算術運算符與右側的數值或算術表達式進行運算,然后將運算結果再賦值給變量。
賦值運算符可以和所有的算術運算符結合構成復合賦值運算符,運算效果等同于上圖的“+=”復合賦值運算符。表3-2列出了“+=、-=、*=、/=、%=”復合賦值運算符的描述及例子。
在復合賦值運算符表格中,“例子”一欄中a是變量。運算順序是先執行算術運算,然后再執行賦值運算。運算符右側的操作數可以是數值、也可以是算術表達式,算術表達式的運算順序同數學運算順序一致。
下面給出復合賦值運算符“+=”的解釋說明,其它復合賦值運算符的運算過程基本相同。
復合賦值運算符“+=”,表示的意思是先將運算符左邊操作數指向的變量值和右邊的操作數執行相加操作,然后再將相加的結果賦值給左邊的操作數指向的變量。例如下面語句:
int a = 10;
a += 20;
此時,變量a等于30,其過程是變量a先與數值20相加,因為變量a的值是10,因此與數值20相加的結果是30,再將30賦值給變量a,此時變量a的值為30。
3、關系運算符
人們在網上挑選商品時,一般會使用電商的商品價格排序功能,將商品按照價格從低到高排列,然后再看商品的評論多少和評論內容來篩選商品,這樣就會大概率買到質優價廉的商品。
電商的商品價格排序功能的核心就是比較商品間的價格高低,也就是比較多個數值的大小,并對數值按從小到大或從大到小排序。
比較兩個數值的大小,也就是要弄清兩個數之間的大小關系。兩個數之間的大小主要存在六種關系,分別是大于關系、大于等于關系、小于關系、小于等于關系、等于關系、不等于關系。例如,對于35和26兩個數來說:35大于26就是大于關系;26小于35就是小于關系。
用于比較兩個數大小的運算符稱為關系運算符,關系運算符是雙目運算符,用在關系表達式中。用于判斷兩個數據之間的關系,例如:大于、等于、不等于,比較的結果是一個整型數值1或 0,1表示“真”,0表示“假”。當條件成立時,運算結果為1;當條件不成立時,運算結果為0。下表列出了C語言支持的比較運算符,表中例子假設A和B不相等且A小于B。
表3-3的A和B是兩個整數類型的變量,且A小于B。運算符“==”檢查A和B的值是否相等,因為A和B不相等,因此關系表達A==B返回0(假),關系表達式A!=B則返回1(真)。
4、條件結構
我們通過一個編程案例來引入條件結構。
編程案例:要求用戶輸入兩個不相等的整數,如果這兩個數的和大于100,則顯示“兩數和大于100”,否則顯示“兩數和小于等于100”
應用我們前面學過的C語言知識,類似這樣的編程要求很難實現,因為程序需求涉及到了條件判斷,并根據條件判斷結果選擇不同的執行分支。在生活中,也常常會遇到許多需要判斷的情況,在這種情況下,需要根據一些條件作出決定和選擇。例如,在我們打算出門時,需要判斷天氣怎么樣,如果下雨了,就要帶上雨傘;外出旅行時,需要根據不同情況,選擇不同的交通工具。
下面我們來學習一種新的程序結構——條件結構。
前面編寫的程序都是“順序流程”,每條語句順序執行。但是在很多情況下,程序并不是按既定的順序執行,而是根據不同請況進行判斷,然后執行不同的操作,這種流程稱為“條件分支流程”,其結構也稱為“條件結構”。
條件結構的核心是條件判斷,在C語言中,條件判斷可以使用關系表達來實現,關系表達式的計算結果返回邏輯真或邏輯假,在C語言中非0數值表示邏輯真,數值0表示邏輯假。若關系表達式返回邏輯真,則執行分支語句塊A,否則執行分支語句塊B,這里的分支語句塊A和分支語句塊B是不同的執行語句塊,在條件結構中,A語句塊和B語句塊永遠不能同時執行。
在C語言中,提供了if-else語法結構來實現條件結構。
其中if和else是C語言的關鍵字,<條件>是一個關系表達式、變量或字面值。變量或字面值的類型應為整數、浮點類型。C語言規定非0的數值為邏輯真,數值0為邏輯假。<條件>執行后,若返回邏輯真執行<分支語句塊A>,否則執行<分支語句塊B>。
在一些情況下,可能只需要執行滿足條件的<分支語句塊A>,而不需要執行不滿足條件的<分支語句塊B>,在這種情況下,就可以把else和<分支語句塊B>省略掉。
現在,我們已經了解了C語言的條件結構和語法,下面探討一下如何在條件結構中使用關系表達式。
例如:要測試兩個整數類型的變量值num1和num2是否相等,可以編寫num1 == num2,然后將其放入一個條件結構中,如下所示:
if ( num1==num2 )
{
……
}
else
{
……
}
如果num1和num2的數值相等,則條件為真,執行if后面的語句塊,否則條件為假,執行else后面的語句塊。
下面我們來實現前面的程序需求,編寫程序前,先繪制程序流程圖。
在程序流程圖中,條件結構使用菱形圖形符號表示,該圖形符號有一個輸入和兩個輸出分支,分別對應條件判斷的邏輯真和邏輯假。
程序清單
#include
void main()
{
int x,y;
// 提示用戶輸入兩個整數
printf("請輸入兩個整數數:n");
// 獲取用戶的輸入
scanf("%d",&x);
scanf("%d",&y);
// 條件結構
if ((x+y) > 100)
printf("x+y >100");
else
printf("x+y<=100");
}
5、邏輯運算符
在數學中,表示一個數值的范圍時,經常用不等式來表述。例如:假設一個數值取值范圍為0到100,設該數值為x,不等式0
例如:要判斷學生的考試成績是否在90至100范圍內,就需要使用邏輯運算符連接兩個關系表達式來完成條件判斷。
下表列出了C語言支持的邏輯運算符,表中假設整型變量A為真(數值為1),整型變量B為假(數值為0)。
假如考試成績用變量score表示,下面的語句可以判斷score是否在90至100范圍內。
score >=90 && score <=100
當score的值在90至100范圍內時,上面語句的運算結果為邏輯真(1)。因為運算符“&&”兩邊的關系表達式的運算結果都為邏輯真(1);當score的值不在90至100范圍內時,上面語句的運算結果為邏輯假(0)。因為運算符“&&”兩邊的關系表達式的運算結果都為邏輯假(0),或有一個關系表達式的運算結果為邏輯假(0)。
例如下面的代碼段執行完成后,bJudge的值是1還是0呢?
int a = 10;
int b = 20;
int c = 15;
int bJudge = c > a && c < b;
上述代碼段的最后一條語句同時出現了賦值運算符、關系運算符和邏輯運算符,C編譯器會先執行哪個運算操作呢?同數學的四則運算一樣,運算符也有優先級,運算順序由高優先級到低優先級下表列出了運算符的優先級。表中優先級欄,數字越小優先級越高,運算符每個運算符用中文頓號分割。
表中小括號‘()’優先級最高,表達式含有小括號的,優先執行小括號的內容,如果包含多個小括號,執行順序是從左到右。
例如,假設變量a的值為12,下述語句的執行會有不同的結果:
(1)執行 a + 18 % 4 ,因為運算符%的優先級高于運算符+,該語句先執行取余運算,再執行加法運算,其結果為14;
(2)執行( a + 18 ) % 4 ,因為小括號的優先級最高,該語句先執行小括號里的表達式a+18,再執行取余運算,其結果為2;
(3)執行 a * ( ( a + 18 ) % 4 ),該語句括號內嵌套括號,執行順序是先執行內層括號的運算,再執行外層括號的運算,其運算結果為24。
了解了運算符的優先級,現在可以確定下述語句:
int bJudge = c > a && c < b;
bJudge的值為數值1(邏輯真)。
邏輯與運算符“&&”連接了2個關系表達式,分別是c > a和c < b,如果這兩個表達式計算結果都為真,則bJudge為1(真),否則bJudge為0(假)。此時bJudge的值為1(真)。該運算符還有一個特點,當左側的關系表達式或變量為0(假)時,則直接返回結果0(假),不再執行運算符右側的表達式。
邏輯或運算符“||”,用于判斷運算符兩邊的條件表達式或整型變量是否有一個為真,如果有一個為真,返回結果為1(真),否則返回0(假)。
邏輯非運算符“!”,用于判斷運算符兩邊的條件表達式或整型變量是否有一個為1(真),如果有一個為1(真),返回結果為1(真),否則返回0(假)。
6、位運算
位運算在嵌入式開發編程中是常用的一種運算,單片機的控制方式都是通過寄存器完成的,寄存器操作一般采用位運算或移位運算。
C語言提供了六種位運算操作符,分別是按位與(&)、按位或(|)、按位異或(^)、按位取反(~)、左移(<<)、右移(>>)。
注意:下面案例使用的數字8和14均為unsigned char類型,因為有符號整數進行位運算后,其符號位可能會改變。
按位與(&)
按位與的運算符是“ & ”,它是一個雙目運算符,它對運算符兩邊的操作數按位進行邏輯與運算,其運算規則是:0&0=0; 0&1=0; 1&0=0; 1&1=1,即:兩位同時為1,結果才為1,否則為0。
例如:8 & 14 的結果是8。
數字8的二進制數是0000 1000,數字14的二進制數是00010 1110,兩個二進制數每位進行邏輯與運算,結果是0000 1000。
按位與運算符在嵌入式開發中應用非常廣泛,它可以用來判斷寄存器中的某一位是否為 1,也可以用來對寄存器某些位進行清零操作。
假設一個8位寄存器AH的值為0x12,對應的二進制數為0001 0010,若需要判斷第2個二進制位(從低位到高位)是否為1,可將AH與0x02進行與運算,若運算結果為0x02,則第2個二進制位為1,否則為0。
void main()
{
unsigned char AH = 0x12;
if( 0x02 == (AH & 0x02) )
{
printf("AH寄存器第2個二進制位為1");
}
else
{
printf("AH寄存器第2個二進制位為0");
}
}
上述代碼段的條件判斷也可以使用下面的語句:
if( AH & 0x02 )
因為0x02的二進制數位0000 0010,只有第2個二進制位為1,其它二進制位都為0,與AH進行與運算后,若AH第2個二進制位為1,則運算結果為0x02,否則運算結果為0,在C語言中,不為0的數值都為邏輯真。
按位或(|)
按位或的運算符是“|”,它是一個雙目運算符,它對運算符兩邊的操作數按位進行邏輯或運算,其運算規則是:0|0=0; 0|1=1; 1|0=1; 1|1=1,即:兩位只要有一個為1,其值為1,其它都為0。
例如:8 | 14 的結果是14。
按位異或(^)
按位異或的運算符是“^”,它是一個雙目運算符,它對運算符兩邊的操作數按位進行邏輯異或運算,其運算規則是:0^0=0; 0^1=1; 1^0=1; 1^1=0,即:如果兩個相應位為“異”(值不同),則該位結果為1,否則為0。
例如:8 ^14 的結果是6。
按位取反(~)
按位取反的運算符是“~”,它是一個單目運算符,它對操作數按位進行邏輯非運算,其運算規則是::~0=1; ~1=0;,即:0變為1,1變為0。
例如:~8的結果是247。
左移(>>)
左移運算符是“>>”,它是雙目運算符,它可以將運算符左邊的操作數向左移動指定的位數,移動的位數由運算符右邊的操作數給出,移動方向為從左到右,移動到左邊界之外的多余二進制位會被丟棄,并從右邊移入0。
例如:8 >>2 的結果是32。
從計算結果可以看出,左移 n 位相當于將這個數乘以 2 的 n 次方。
右移(<<)
右移運算符是“<<”,它是雙目運算符,它可以將運算符左邊的操作數向右移動指定的位數,移動的位數由運算符右邊的操作數給出,移動方向為從右到左,移動到右邊界之外的多余二進制位會被丟棄,并從左邊移入0(無符號整數),對于有符號數整數,需要注意符號位的處理,如果移位的操作數是正數,右移時會在左邊填充 0,如果是負數,右移時會在左邊填充 1。
例如:8 >> 2 的結果是2。
從計算結果可以看出,右移 n 位相當于將這個數除以 2 的 n 次方。
位運算可以應用到位掩碼技術,位掩碼用于操作和檢測一組二進制數據中的特定二進制位,通過掩碼,我們可以方便地設置、清除或者翻轉一組二進制數據中的特定二進制位。例如,我們可以定義一個掩碼來提取一個字節的低4位。
#include
void printf_binary(unsigned char n);
void main()
{
unsigned char AH = 0xab;
unsigned char mask = 0x0f;
printf_binary(AH);
printf_binary(AH&mask);
}
void printf_binary(unsigned char n)
{
char i=0;
for(i=0; i< 8; i++ )
{
if(n&(0x80 > >i)){
printf("1");
}else
{
printf("0");
}
}
printf("n");
}
在上面的程序代碼中,定義了printf_binary()函數,該函數將傳入的參數n轉換為二進制數并輸出,函數內用到了循環語句,它可以重復執行相同的代碼段,循環語句的語法后面還會講述。
變量mask是我們定義的掩碼 ,變量的值為0x0f,它的二進制表示為 00001111,mask與變量AH進行位與運算,運算的結果為變量AH的低4位。程序的輸出結果見下圖。
位運算一般在嵌入式開發中應用,用于配置單片機的寄存器,也會使用到一些高效的程序算法中。
7、運算符的優先級
C表達式可能存在多個運算符,運算符之間存在優先級的關系,級別高的運算符先執行運算,級別低的運算符后執行運算算,下表列出了運算符的優先級。表中優先級欄,數字越小優先級越高,運算符每個運算符用中文頓號分割。
表中小括號‘()’優先級最高,表達式含有小括號的,優先執行小括號的內容,如果包含多個小括號,執行順序是從左到右。
在C語言中,運算符的優先級決定了表達式中運算執行的順序。高優先級的運算符將在低優先級的運算符之前被執行。例如,乘法和除法運算符的優先級高于加法和減法運算符。
以下是如何判斷C語言運算符優先級的步驟:
(1)了解C語言中的運算符類型。C語言中有多種運算符,包括算術運算符、關系運算符、邏輯運算符、位運算符、賦值運算符等。每種運算符都有不同的優先級。
(2)確定運算符的優先級。C語言中,運算符的優先級由高到低分為七個級別,下面列出了這些級別,以及相應的運算符:
- 后綴運算符:++、--
- 一元運算符:++、--、+、-、~、!
- 乘法 / 除法 / 取余:*、/%、
- 加法 / 減法:+、-
- 移位運算符:<<、>>
- 關系運算符:<、>、<=、>=
- 等于不等于:==、!=
- 位與運算符:&
- 位異或運算符:^
- 位或運算符:|
- 邏輯與運算符:&&
- 邏輯或運算符:||
- 條件運算符:? :
- 賦值運算符:=、+=、-=、*=、/=、%=、<<=、>>=、&=、^=、|=
(3)根據優先級確定表達式的執行順序。在復雜的表達式中,根據優先級確定運算執行的順序非常重要。例如,在表達式a = b + c * d
中,乘法運算將在加法運算之前執行,因為乘法的優先級高于加法。
以下是一段根據C語言自增、自減、關系運算符、算術運算符優先級的示例代碼,代碼中包含了對這些運算符的用法的注釋,并附帶了示例和預期的輸出結果。
#include
int main() {
int a = 5; // 初始化變量a為5
int b = 3; // 初始化變量b為3
// 算術運算符優先級: 加法 > 減法 > 乘法 > 除法 > 取余
// 關系運算符優先級: < > <= >= == !=
// 自增自減運算符優先級: ++ --
// 算術運算符示例
printf("a + b = %dn", a + b); // 輸出: a + b = 8
printf("a - b = %dn", a - b); // 輸出: a - b = 2
printf("a * b = %dn", a * b); // 輸出: a * b = 15
printf("a / b = %dn", a / b); // 輸出: a / b = 1
printf("a % b = %dn", a % b); // 輸出: a % b = 2
// 關系運算符示例
printf("a > b? %sn", a > b ? "Yes" : "No"); // 輸出: a > b? No
printf("a < b? %sn", a < b ? "Yes" : "No"); // 輸出: a < b? Yes
printf("a >= b? %sn", a >= b ? "Yes" : "No"); // 輸出: a >= b? Yes
printf("a <= b? %sn", a <= b ? "Yes" : "No"); // 輸出: a <= b? No
printf("a == b? %sn", a == b ? "Yes" : "No"); // 輸出: a == b? No
printf("a != b? %sn", a != b ? "Yes" : "No"); // 輸出: a != b? Yes
// 自增自減運算符示例
printf("a++ + b = %dn", a++ + b); // 輸出: a++ + b = 8 (這里,a先自增,然后和b相加,所以原來的a=5+1=6)
printf("a + b = %dn", a + b); // 輸出: a + b = 8 (這里,a先和b相加,然后自增,所以原來的b=3)
printf("a-- + b = %dn", a-- + b); // 輸出: a-- + b = 11 (這里,a先自減,然后和b相加,所以原來的a=6--)
printf("a + b = %dn", a + b); // 輸出: a + b = 14 (這里,a先和b相加,然后自減,所以原來的b=3)
return 0;
}
上述代碼展示了C語言中的算術運算符、關系運算符以及自增自減運算符的優先級和用法,每行代碼前添加了詳細的注釋,運行這段代碼應該沒有錯誤,并會按照預期的方式輸出結果。
評論
查看更多