C++筆記-邏輯與運算子

表達式 Expression

有人常言道:「表達式(計算式)的天職,就是得到一個值。」

1 + 2 是一個表達式,其中 1 是一個運算元,2 是另一個運算元,而 + 是運算子。

1 + ( 2 - 3 ) 也是一個表達式,這個表達式裡還有一個表達式 ( 2 - 3 ),稱為複合表達式(Compound Expression)

而等等會看到的 a = 5,其實也是一個表達式,將 5 賦值給 a,那麼這個表達式得到的值當然就是最後賦值給 a 的數值。

運算子 Operator

運算子可簡單區分為一元(單元)運算子、二元運算子以及三元運算子。

每個運算子都有執行的優先順序,如同數學有先乘除後加減,以下是之後可能會在 c++ 看到的運算子:

優先度運算子描述閱讀順序例子
1::作用域->std::cout « endl;
2++/-- () [] . ->先回傳再加減1 \ 函式呼叫 \ 陣列存取 \ 物件存取成員 \ 指標存取成員->i++/i--; int a = f(x); int a[10]; obj.cmp = 0; ptr->val = 0;
3++/-- +/- ! ~ (Type) * & sizeof先加/減1再回傳 \ 正負號 \ 邏輯NOT \ 位元取反 \ 強轉類型 \ 指標取值 \ 取址 \ 佔用位元組大小<-++i/--i +/-1 if(!true) a = ~a; int i=int(doublex); int k = *a; int *k = &a; cout « sizeof(int);//4
4* / %乘 \ 除 \ 取模->int a = 8*8; int a = 20/6; int a = 6%4;
5+/-加 \ 減->int a = 6+4;
6»/«位元右 \ 左移->int a = 4 » 3;
7</<=/>/>=大小等於->if(a < 0)
8==/!=等於/不等於->while(a!=0)
9&位元AND運算->n = x&1
10^位元XOR運算->n = x^1
11|位元OR運算->n = x|1
12&&邏輯AND->if(1==3 && 2==2)
13||邏輯OR->if(1==3 || 2==2)
14c?p1:p2三元條件運算(可當成if-else)<-int i = a>b?a:b;
15=/+=/-=/*=//=/%=/«=/»=/&=/^=/|=賦值<-a+=3;b&=1;
16,逗號->int i,j,k;

賦值運算子 Assignment operator

用於修改容器所存的值,比如 =,而 a = 5 這個表達式中,就是將數字 5 賦值給 a

算術運算子 Arithmetic operator

五則運算

在 C++ 中,除了我們熟知的加 +-*/,還多了一個模運算 %,或稱取餘運算,也就是做除法後,看餘數是多少。

比較運算子

用於比較運算元的關係,如大於 >、小於 <、相等 == 以及不等 !=

要特別注意的是,相等是兩個等號 ==,一個等號 = 的是賦值的意思而不是相等。

位元運算子

位元運算AND、OR、XOR,
它們的運算方式都要從二進位表示法來看,
並一個一個位數來做計算。

使用AND運算結果如下:

PQ結果
000
100
010
111

舉例:

$9_{10}\ \&\ 8_{10}= 1001_2\ \&\ 1000_2=1000_2=8_{10}$

可觀察只有當兩位元都是1時輸出才是1。

我們可以將它應用在判斷奇偶數:

1
cout << (x&1?"Yes":"No") ;

使用OR運算結果如下:

PQ結果
000
101
011
111

舉例:
$ 10_{10}\ |\ 8_{10} = 1010_2\ |\ 1000_2 = 1010_2 = 10_{10} $$

只要有位元為1,則輸出就是1。

使用XOR運算結果如下:

PQ結果
000
101
011
110

舉例:

$ 10_{10} \oplus 8_{10} = 1010_2 \oplus 1000_2 = 0010_2 = 2_{10} $

兩個位元只能有一個是1,其他情況都回傳0。

它的用途更廣,你可以用它將兩個數交換:

1
2
3
a^=b;
b^=a;
a^=b;

可以判別一個陣列中哪個數缺少:

1
2
3
4
5
int a[]={1,2,3,5,6,7,8,9};
int n=0;
for(int i=0;i<9;i++) n^=i;
for(int i=0;i<9;i++) n^=a[i];
cout << n;

可以做大小寫轉換:

1
2
3
4
5
6
char tolower(char c){
	return (c>='A'&&c<='Z')?c^32:c;
}
char toupper(char c){
	return (c>='a'&&c<='z')?c^32:c;
}

另外再介紹位元左右移,就是將數寫成二進位後乘十或除十,相當於十進位中乘二或除二。

1
2
3
4
int a=8;
cout << a << endl;
cout << (a<<1) << endl; // 注意括號,以免跟輸出的<<混淆
cout << (a>>1) << endl;

陳述式 Statement

在 C++ 裡使用 Statement 表示完整的操作,其中大部分陳述式會以分號 ; 結尾, 有些 Statement 裡還會包含另一個 Statement。

int a = 0; 這是一個完整的程式陳述句

int b = a; 這也是一個完整的程式陳述句

c = a + b; 這也是一個完整的程式陳述句

問題來了:

1
2
3
4
int main(){
  5;
  return 0;
}

5; 是不是一個 Statement 呢?

複合陳述式 Compound Statement

又稱為 區塊 block,由一些小的 statement 組成,這些 Statement 稱為 substatement,

比如說 { statement1... }

我們常利用 {} 來幫程式碼分好幾個區塊。

變數生命週期

複合陳述式都有自己的 scope,當離開 scope 後,scope 裡宣告的變數都會被丟掉(解構)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <iostream>
using namespace std;
int main(){
  { 
  int a = 5; 
  }
  
  cout << a << endl;
  
}

以這個程式例子來說,main 那一行後面有一個 {,對應最後一行的 } 這是一個 scope, 而裡面有一個 scope 宣告一個變數 a,然而當離開這個 scope 後,a 將會被程式解構, 因此下面的輸出 a 將因為看不到 a 而發生編譯錯誤。