編程文法分析之“優先順序”和“結合律”

來源:互聯網
上載者:User

標籤:

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

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

 

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

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

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

 

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

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

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

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

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

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

如果您多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截取的一個例子)

運算式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));

編程文法分析之“優先順序”和“結合律”

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.