程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 編程語法分析之“優先級”和“結合律”,語法優先級

編程語法分析之“優先級”和“結合律”,語法優先級

編輯:關於C語言

編程語法分析之“優先級”和“結合律”,語法優先級


上節《編程語法分析之從表達式說起》中說到表達式,他的主要作用就是返回一個值!那這個值具體是多少,就要看表達式的整個運算過程。要理解表達式的運算過程就必須了解“優先級”和“結合律”。

之前講到表達式,一般有操作數和操作符(或者叫做運算符)組成。“優先級”和“結合律”都是針對操作數和操作符來分析的。現在就來看張表:

image

image

 

這張表介紹了“優先級”和“結合律”,優先級數字越小,優先級越高。在優先級相同的情況下,才會考慮“結合律”!

注意上表中,結合方向一欄,右到左的意思就是右結合,左到右,就是左結合。簡單說,“結合律”就僅僅分為“左結合”與“右結合”!

為了很好的理解“優先級”和“結合律”我舉幾個有意義的例子。

 

例1、這個例子主要從“結合律”出發,討論左結合與右結合的特點。

所謂結合,就是多個東西結合成為一個整體,而成為一個新的東西。當一個操作符是一個左結合且為雙目運算符時,他會把他左邊的東西整個當作一個整體並與之結合,右邊的只認離他最近的一個。(右結合與之相反)

  如:(這是一個C++例子,能很好的理解結合這個概念)wpsBFD1.tmp

對於第二個<<運算符而言,他會把他左邊的全部當中一個整體,及把wpsBFD2.tmp當作一個整體,這個整體其實就是個表達式,他是一個值,他的值就是std::cout的值。

而對於第一個<<運算符而言,在他的右邊他只認“Hello,World!”及右邊的只認離他最近的一個。

在原文<Accelerated C++>中是這麼解釋的;

wpsBFE2.tmp

如果您多C++不熟悉,我們就來看第二例子:

 

例2、一個超級簡單的表達式,此時你應該有更深的認識:

      a + b + c

      首先,此表達式中,操作符都是加號,大家優先級相同,所以轉而考慮結合性,+是左結合。

      所以第一個加號先與a結合,並且只認右邊和他最近的b,而對於第二個加號,會把a+b當作一個整體,並與之結合,然後只認右邊和他最近的c。結果就是((a) + b) + c 。

如果前兩個例子都不過瘾,我們來看第三個例子:

 

例3、這個例子需要兼而考慮優先級”和“結合律”。

(*  (  ( void (*)() )0  )  )()

這裡操作符有小括弧——強制轉換符(形式上也是小括弧),解引用符,操作數只有一個,就是0;操作符都是針對操作數的。

我們先從0開始看,和0最近的是小括弧,這個小括弧裡面是個void (*)()這其實是個類型——函數指針類型,用小括弧把類型括起來,這個小括弧其實是強制轉換符。那麼( void (*)() )0 這個表達式結合起來,就表示把0,強制轉換為函數指針類型。

在往外又是一個小括弧,這個小括弧就是說小括弧內部是一個結合的整體。此時由於( void (*)() )0是一個整體而且表示一個函數指針,所以把( void (*)() )0替換為p,結果就是(* p )(),這句話的意思其實就是利用函數指針p調用函數。而這p其實是指向地址0的。所以這句表達式的副作用就是,讓程序指針PC跳到地址0,及完成一個軟件復位的功能。

進一步討論如果,去掉其中的一層括號:

(*  ( void (*)() )0    )() 

那麼一開始有兩個操作符針對操作數0,一個是強制轉換符(類型),一個是解引用*觀察上表可知(類型)和 * 的優先級都是2,優先級相同,而結合性是右結合,簡化一下表達式再分析:

(*  ( 類型 )0    )()

因為是右結合,所以*會把右邊的( 類型 )0當作一個整體,及 ( 類型 )先和0結合,所以結論是去掉這層括號含義不變!

趁熱打鐵,我們來看第四個例子:

 

例4、ph->pNext->pNext->pNext->pNext->pNext

這種表達式通常是在鏈表的訪問中見到,別看他這麼長其實也就返回是一個值,所以不必怕它。

ph是個頭指針,->這個符號查表得知是左結合,及左邊的看成整體,右邊的只認一個那麼ph->pNext就可以被單獨分離出來並且結合到一起成為一個整體,

ph->pNext看成整體之後,其實就是返回一個指針,及第0個節點中存放的指針值!而這個指針指向第1個節點。所以ph->pNext可以用p1代替。

剩下的p1->pNext->pNext->pNext->pNext,依照上面的方法如法炮制就得到p2->pNext->pNext->pNext。最終就得到p4->pNext.

如果說ph指向第0個節點,p4->pNext最終的結果其實就是第4個節點中存放的指針值,指針指向第5個節點。這也就是整個表達式的結果。

最後一個例子引入,逗號表達式作為飯後甜點。

 

例5、逗號表達式

逗號表達式形如:表達式1,表達式2

首先,逗號表達式,也是個表達式,逗號表達式作為整體也返回一個值!

其次,整個逗號表達式的結果為表達式2的結果。

可能有的同學要發問了,那表達式1不是個打醬油的?其實,表達式1一般是為表達式2做個鋪墊,如:(從MFC截取的一個例子)

wpsBFE3.tmp

表達式1其實是給str賦值,表達式2就是一個比較語句,那麼if只會判斷表達式2的結果是否為真,而不會理會表達式1的返回值。

在使用逗號表達式時,一定要注意優先級的問題,因為“,”的優先級比“=”的優先級還要低。

例如:a = 3*5 , a*4; 由於“,”的優先級比“=”的優先級低,所以a = 3*5先結合,算出a等於15,然後a*4得到60.再根據“整個逗號表達式的結果為表達式2的結果”

所以整個表達式(a = 3*5 , a*4)的結果是60.

具體測試方法為:

int a;

printf("%d",(a = 3*5 , a*4));

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved