近日在csdn上閒逛的時候,注意到乙個帖子:
((*strdest++=*strsrc++)!='\0'); 哪兒前輩可以解釋下裡面具體執行的步驟呢?
對於這樣的表示式,我們通常會有這樣三種看法:
1.這種寫法不但沒有錯誤(當然也沒有bug),而且寫法緊湊。
2.這種寫法雖然沒有錯誤,但是不夠直觀,理解起來有點麻煩,可能還會導致理解錯誤。
3.這種寫法中存在未定義的地方,執行結果可能是錯誤的。
粗略來看,這三種說法都有點道理。我頓時有了刨根問底的興趣,想對這個問題進行一次深入的分析。對於這種組合表示式,在分析的時候我們應該抓住兩個關鍵的概念:優先順序(precedence)和關聯性(associativity)。
1.優先順序(precedence)。優先順序決定了那些表示式的值先被評估,那些表示式的值後被評估。通常情況下,優先順序高的表示式的值先被評估出來後,然後用評估的結果再去評估那些優先順序低的表示式。所以如果我們將優先順序搞反了,評估出來的結果是錯誤的。
2.(associativity)。對於二目表示式,關聯性決定了左邊的表示式還是右邊的表示式先被評估,先被評估出來的結果再用來評估另外的表示式。
再抓住這兩個關鍵的同時,我們還應該分清什麼是表示式的值,什麼是變數的值。我們在評估表示式的時候,我們感興趣的是表示式的值,而不是構成表示式的某些變數的值。在很多情況下,表示式的值和某些變數的值是一致的,所以我們很容易混淆表示式的值和變數的值。要知道,在有些情況下,表示式的值並不和某些變數的值相同。
有了上面的理論來武裝我們,對表示式的分析就顯得游刃有餘了:
1. 很明顯,上面的表示式是乙個組合表示式。組合表示式由子表示式組成,子表示式又可能是組合表示式,這樣就形成了乙個樹狀的資料結構。對表示式的評估就類似於對樹結點的遍歷。首先我們應該注意到"()"操作符,它具有最高的優先順序,所以從整體來看,整個表示式應該是個"!="操作。"!="左邊又是乙個組合表示式,而右邊是乙個常量"\0',很明顯下面的工作就是評估(*strdest++=*strsrc++)。
2.在這一步,我們要對表示式(*strdest++=*strsrc++)進行評估。由於賦值表示式具有較低的優先順序,所以表示式 又可以寫成:(*strdest++) = (*strsrc++),所以整個表示式是個"="操作,"="左邊又是乙個組合表示式,右邊也是乙個組合表示式,這裡就需要從關聯性來判斷左邊還是右邊也被評估。由於",海娜粉;="的關聯性是從右到左,所以(*strsrc++)先被評估,(*strdest++)後被評估。
2.1 在這一步,我們要對表示式(*strsrc++)進行評估。由於"++"的優先順序大於"*",所以表示式又可以寫成:*(strsrc++)。我們要先對表示式strsrc++進行評估,然後用表示式的值再去評估*(strsrc++)的值。對於表示式strsrc++,這裡要需要注意區分變數的值和表示式的值。對於"後增1"表示式,表示式的值是變數strsrc的值,然後變數strsrc的值會"加1",也就是說表示式的值是strsrc變化前的值,而strsrc的值會發生變化。值得注意的是,我們知道strsrc的值會發生變化,但是我們卻不知道strsrc的值發生變化的具體時間,這個變化具體的執行時間由編譯器決定了,這就決定了任何依賴strsrc的表示式的值是不確定的,具體的值依賴編譯器的實現。完成了對strsrc++的評估後,取值操作符就對表示式的值所對應的記憶體空間進行取值操作。
2.2 在這一步,我們要對表示式(*strdest++)進行評估。具體的評估的分析完全和2.1中的分析一致。
2.3 在這一步,我們要對表示式(*strdest++) = (*strsrc++)進行評估,這是個賦值表示式,將右表示式的值賦給左邊表示式的值。值得注意的是,對於賦值表示式,表示式本身的值等於左邊子表示式的值。
3.由於"!="表示式左邊的子表示式的值已經被評估出來了,下面就執行"!="操作。"!="表示式的是乙個布林值。
通過以上深入的分析,我們知道這個表示式完成了以下多個功能:
1.對於指標strdest, strsrc,將strsrc所指的記憶體空間的值賦給由strdest所指的記憶體空間。
2.判斷賦值後的strdest所指的記憶體空間的指是否等於0。
3.對於指標strdest,strsrc,他們的值分別加1,即指向下乙個元素。
我們可以看出,乙個表示式完成了三個功能,表示式寫的確實"相當緊湊"。而且這個表示式的值是可以確定的,因為所有的分析都是建立在c 標準的基礎上。對於能否在實踐的**中使用這樣的**,這就智者見智了,關鍵一點就是要遵循專案的**規範。
複雜表示式的執行步驟
近日在csdn上閒逛的時候,注意到乙個帖子 strdest strsrc 0 哪兒前輩可以解釋下裡面具體執行的步驟呢?對於這樣的表示式,我們通常會有這樣三種看法 1.這種寫法不但沒有錯誤 當然也沒有bug 而且寫法緊湊。2.這種寫法雖然沒有錯誤,但是不夠直觀,理解起來有點麻煩,可能還會導致理解錯誤。...
C語言求得表示式的字尾表示式
獲取字尾表示式的原理是用乙個字元陣列來存放字尾表示式,用乙個棧來暫時存放運算子,入棧出棧和字元陣列的儲存規則為 一.當字元是運算元,直接存入字元陣列中 二.當字元不是運算元,分三種情況討論 1.字元是 當前字元直接入棧 2.字元是 一直出棧,將出棧的字元存入字元陣列中,直到棧頂元素是 時,將棧頂元素...
C語言 逗號表示式
c語言提供一種特殊的運算子 逗號運算子。用它將兩個表示式連線起來。如 3 5,6 8 稱為逗號表示式,又稱為 順序求值運算子 逗號表示式的一般形式為 表示式1,表示式2 逗號表示式的求解過程是 先求解表示式1,再求解表示式2。整個逗號表示式的值是表示式2的值。例如,上面的逗號表示式 3 5,6 8 ...