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 pbeg
Operand 運算順序不是固定的,通常不會造成問題,但如果兩邊有用到同一 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 意見:
張貼留言