每一個表達式都有一個結果,字面值常量也是表達式,其結果就是值本身。除了特殊用法外表達式的結果是右值。是左值的情況也有,比如++i;這個表達式就是一個左值;還有逗號運算符的結果是表達式最右側操作符德值,如果最右是一個左值的話,那整個逗號表達式就是左值。
表達式涉及到操作符和操作數,操作符有優先級規則,有結合性,還有操作數的求值順序。就操作數的求值順序而言,比如f1() * f2();兩個函數的返回值進行相乘,但無法確定先調用哪個函數。
操作符%成為“求余”或是“取模”,操作數為整型,其中bool類型也可以。
對於“%”和“/”這兩個操作符來說。如果只有一個操作數為負數,那這兩種操作的結果(這裡僅指絕對值,不考慮符號)都是取決於機器的;取模運算的符號也是取決機器的;但除法操作的結果肯定是負數。舉個例子:
21/ -5:依賴機器的,結果是-4或是-5
21% -5:依賴機器的,對應的結果是1或是-4
在邏輯表達式中,邏輯與和邏輯或總是先計算左操作數,再計算右操作數。只有在僅靠左操作數無法判斷表達式結果時,才會求解器右操作數。我們稱這種運算原則為“短路求值”。
相等測試與bool字面值。由於bool中的true可以轉換為1,所以如何判斷某值與true相等卻成了難題。這裡要考慮某值val的類型,如果val是bool類型的,那麼正確的判斷就是if ( val ) { … };即可。如果val不是bool類型,那判斷就和if ( val ==1 ) {…};等價了;假如val是整型,那if ( val )則是當且僅當val為0時為邏輯假,其余的值,無論正負都是邏輯真。
位操作符的操作數是整型,這裡的整型不僅可以是正整數,也可以是負整數。但對於負整數的符號位處理方式,不同的機器有著不同的實現,所以盡量使用無符號正整數來作為位運算的操作數。
位運算中的左移和右移操作原則。無符號來說,左移是數值擴大,右側補0;右移是數值減小,左側補0。對於有符號來說,其右移過程中,左側可能是補0將其變成正數,也可能補1不改變其符號,這都依賴於機器。
Cout<<42 + 10;正確,因為+高於<<
Cout<<(10 < 42);也正確,因為有括號
Cout<<10 < 42;錯誤,因為<<高於關系運算符。Cout<<10之後返回一個ostream的引用,返回引用的目的是可以連續輸出,達到流的效果。將一個ostream引用和42對比較是無意義的。
賦值操作的右結合性。
Intival, jval; ival = jval = 0;這是合法的。賦值運算符也有返回值,先執行jval= 0,返回一個整型再賦給ival。賦值運算符具有很低的優先級。
判等和賦值容易出錯的地方。If ( i = 42 )這句話實際上是對的,字面解釋是把42賦給i,然後判斷i的真或假。但這顯然是無意義的,這句代碼像是被寫錯的,原意是if ( i== 42 )。為了能避免這樣的隱蔽錯誤,可以寫成if ( 42 == i)這樣一來,假如少寫了個“=”if( 42 = i )就是編譯錯誤,可以及時發現。
關於如何交換兩個數的值.
算術方法:a = a + b; b = a – b; a = a – b;
位運算方法: a ^= b; b ^= a; a ^= b;
對於i++和++i的更深層次討論,在一個長的表達式中有多個關於i的自增和自減操作,這樣的表達式的結果是依賴機器的。這裡面有一個概念是任何語言的表達式求值都逃不掉的,那就是序點。序點直觀來說就是當執行到此序點時必須保證序點前的子表達式已經求出結果。在C++中規定,上一個和下一個序點之間,對象的值至多被修改1次。至於規定表達式中的哪些地方設置序點,這有機器實現決定。值得一說的是在長表達式中不要試圖多次對一個對象修改。
I++是右值,++i是左值。
I++的具體實現:
Constint int::operator++(int)
{
IntoldValue = *this;
++(*this);
ReturnoldValue;
}
++i的實現細節:
Int&int::operator++()
{
*this+= 1;
Return*this;
}