Expression
運算式 (expression) 由運算元 (operand) 與運算子 (operator) 所組成,最終計算產生一個結果 (result)。
-
Order of Evaluation
想要計算 expression 的話,就必須知道運算子運作及其先後順序。這裡的 * 號就不是 pointer 而是相乘,然後再來是基本的先乘除後加減。
cout << 5 + 10 * 20 / 2 << endl; // 105 cout << 6 + 3 * 4 / 2 + 2 << endl; // 14 cout << (6 + 3) * (4 / 2 + 2) << endl; // 36 cout << ((6 + 3) * 4) / 2 + 2 << endl; // 20 cout << 6 + 3 * 4 / (2 + 2) << endl; // 9
-
Lvalues and Rvalues
有寫過一篇 Lvalues and Rvalues 也可以參考。這裡紀錄此書寫大概的定義,當我們將一個 object 視為 rvalue 使用,使用的是此 object 的值 (contents)。當我們將一個 object 視為 lvalue 使用,使用的是此 object 的「存在」(記憶體位置)。還有一點也很重要,lvalue 可以代替 rvalue,但反之 rvalue 卻不能代替 lvalue。
int a = 1; // a = lvalue, 1 = rvalue int b = a + 1; // a = lvalue, a = rvalue (lvalue 代替 rvalue) int 1 = a; // Error, 1 != lvalue (rvalue 不能代替 lvalue)
Operators
-
Logical and Relational Operators
Logical Operators 和 Relational Operators 回傳 bool。Logical Operators AND 跟 OR 永遠都會先計算左側再來計算右側。這裡想特別紀錄的是 && 跟 ||,&& 代表只有左側計算出來是 True 才會計算右側,|| 則是只有左側計算出來是 False 才會計算右側。這可以寫出一些流程控制而不是使用典型的 if else。Relational Operators 則是 >, <, >=, <=, ! 這些。// 以下這兩個 val 都會被轉換成 bool if (val) { /* ... */ } // true if val is any nonzero value if (!val) { /* ... */ } // true if val is zero // 有了上面兩個例子,我們看似可以將其改寫成以下寫法 if (val == true) { /* ... */ } // 這個會產生問題,只要 val 的型別不是 bool // 假設 val 是 int,true 會被轉換成 int 也就是 1 跟原先的任何 nonzero value 相去甚遠 if (val == 1) { /* ... */ } // true if val is 1
-
Assignment Operators
最常見就是等號 (=)。Assignment 是 Right Associative,以下有程式碼示範。另外 Assignment Operators 執行順序較低通常會用括弧輔助。
int ival, jval; ival = jval = 0; // ok: each assigned 0 // 對於右邊的 assignment,jval = 0 // 對於左邊的 assignment,ival = (jval = 0) // jval assigned 0 後,回傳 jval (ival = jval),ival = 0// 原先邏輯 int i = get_value(); while (i != 42) { // do something ... i = get_value(); } // 改寫,用括弧輔助 int i; while ((i = get_value()) != 42) { // do something ... }
-
Increment and Decrement Operators
++ -- 用來做 Increment 和 Decrement,兩個都有 prefix 跟 postfix 的寫法,效果如下程式碼示範。要注意的是要盡量用 prefix 來做運算,因為你通常不會需要做增減前的 value,而 postfix 會 copy 一份增減前的 value 來做回傳。int i = 0, j; j = ++i; // j = 1, i = 1: prefix yields the incremented value j = i++; // j = 1, i = 2: postfix yields the unincremented value // 需要 postfix 的場合 auto pbeg = v.begin(); // print elements up to the first negative value while (pbeg != v.end() && *beg >= 0) cout << *pbeg++ << endl; // print the current value and advance pbegOperand 運算順序不是固定的,通常不會造成問題,但如果兩邊有用到同一 variable 且用了 Increment 或 Decrement Operators 問題就會浮現。
// 原先邏輯是把 s 裡的 char 都改成大寫 // the behavior of the following loop is undefined! auto it = s.begin() while (it != s.end() && !isspace(*it)) *it = toupper(*it++); // error: this assignment is undefined // 會有兩種結果 // 第一種輸出 ABCDEFG *beg = toupper(*beg); // 先執行左邊的 Operand,Output: ABCDEFG *(beg + 1) = toupper(*beg); // 先執行左邊的 Operand,Output: aAAAAAA
-
Shift Operators (aka IO Operators) Are Left Associative
cout << "hi" << " there" << endl; ( (cout << "hi") << " there" ) << endl; cout << 42 + 10; // ok: + has higher precedence, so the sum is printed cout << (10 < 42); // ok: parentheses force intended grouping; prints 1 cout << 10 < 42; // error: attempt to compare cout to 42!
0 意見:
張貼留言