# 逗號運算子
## 共同討論
田雅今, 叢壯滋, 高唯恩, 王頌晴, 謝曜宇, 古詠熙, 吳珩睿, 邵中叡, 郭明勳(Sort by student ID)
筆者: 新世紀芙茵戰士
## 前言
上一堂課老師提到逗號運算式(comma operation),由於我們都不太理解其中奧妙,於是就在實習課上討論起來,也就有了這篇文。
## 問題
我們拿了其中一張PPT的程式跑跑看。

```c=
#include <stdio.h>
int main(){
int k1, k2;
int i = 1,j = 10;
k1 = ++i, j + 1;
k2 = i + 1, j + 1;
printf("%d %d \n", k1, k2);
}
```
結果出乎意料,
```
2 3
```
是2跟3而不是PPT上說的11,於是我們就更confused了。
## 嘗試
於是我們嘗試了下面的寫法,也就是在多寫了括號:
```c=
#include <stdio.h>
int main(){
int k1, k2, k3, k4,;
int i = 1, j = 10;
k1 = ++i, j + 1;//i = 2, j = 10
k2 = i + 1, j + 1;//i = 2,j = 10
k3 =( ++i, j + 1);//i = 3, j = 10
k4 = (i + 1, j + 1);//i = 3, j = 10
printf("%d %d %d %d %d %d\n", k1, k2, k3, k4, i ,j);
}
```
結果為:
```
2 3 11 11 3 10
```
因此我們可以知道,要達到PPT上的11,需要額外加括號,另外可以特別注意i與j值的變化。
## 解決
要解決問題我們可以從逗號運算子的運算跟特性講起,逗號運算子的特性如下:
**1.左相依性(left associative)**
```
ex:
a , b , c;
等於
(a , b) , c;
```
也就是由左至右計算。
**2.優先序低於其他運算子**
```
ex:
i++ , i + 1;
電腦會優先計算逗號運算子以外的其他運算子,
也就是說電腦會自動讀成
(i++) ,(i + 1)
```
至於**運算**則就更簡單了,如下:
```
expr1 , expr2
```
先計算expr1並把expr1的值拋棄(拋棄容易讓人誤解,可以當作不鳥它),然後計算expr2,接著回傳expr2的值。
舉例:
```
int i = 1 ;
i++ , i + 1;
```
電腦會先計算(i++),i的值會被更新為2,接著拋棄(或不鳥)(i++)的值,然後計算i+1並回傳(i+1)的值,也就是3,所以(i++,i+1)這個式子的值就是3。那麼請問現在i等於多少?
答案是2,因為(i+1)並沒有儲存到i。
現在我們可以看看之前的程式
```
int i = 1, j = 10;
k1 = ++i, j + 1;
printf("%d",k1)
```
我們或許認為k1的值為(j+1),然而根據前述的特性二,電腦實際上讀到的是:
```
(k1 = ++i), (j + 1);
```
這時印出k1,當然就會是i++的值也就是2,而不是11,相對來說((k1 = ++i), (j + 1))的值才是11。
因此,下面的式子也同理。
```c=
#include <stdio.h>
int main(){
int k1, k2, k3, k4,;
int i = 1, j = 10;
k1 = ++i, j + 1;//電腦讀成(k1 = ++i),(j + 1)
k2 = i + 1, j + 1;//電腦讀成(k2 = i + 1), (j + 1)
k3 =( ++i, j + 1);//電腦讀成k3 =( ++i, j + 1) ,回傳(j+1)
k4 = (i + 1, j + 1);//電腦讀成k4 = (i + 1, j + 1), 回傳(j+1)
printf("%d %d %d %d %d %d\n", k1, k2, k3, k4, i ,j);
}
```
所以真相大白,若沒加括號電腦可能會根據逗號運算子低於其他運算子的特性,誤解你原本要表達的意思。
## 結論
為了避免編譯器誤解你的意思,再使用逗號運算子時,括號我建議一律淦你@加爆!
不過教授的PPT不小心寫錯,反而促成我們在實習課上不斷實驗並嘗試去了解逗號運算子,想起來真是奇妙又有趣。
## 參考資料
#### 逗號運算子的特性與運算:
C Programming: A Modern Approach (page 109)

(照片由古詠C提供)
#### 相依性跟運算子優先序:
https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
#### 逗號運算子:
https://docs.microsoft.com/zh-tw/cpp/cpp/comma-operator?view=msvc-160
#### 田雅今助教的IG:
https://www.youtube.com/watch?v=dQw4w9WgXcQ
#### PS
第一次用hackmd同時也是第一次發文,別鞭太大力,有錯歡迎指正