外星代碼生成術之逗號運算符
縮減代碼不意味著增加可讀性,恰恰相反,過分的縮減代碼反而會使代碼更難懂,難以維護。本文不提倡濫用扭曲化的外星C語法,只是作為一個集趣式的記錄,為初學C派系語言的讀者簡單介紹一下那些莫名其妙的代碼是如何造出來的。
C派系語言為我們提供了許許多的奇怪的運算符,最奇怪的運算符之一當數逗號運算符,它本身并沒有太多實際意義“運算”,只是計算各個運算項的值,然后將最右邊的運算項的值返回。但這一點使得我們有可能將多個表達式合成為一個:
a = 1;
b++;
c *= 4;
合并為:
a = i, b++, c *= i;
呵,好像意義不大,但如果是在循環中使用,就不一樣了:
while (i < n)
{
a = i;
b++;
i++;
}
可簡寫為:
while (a = i++, b++, i < n) ; /* 注意分號不能少 */
在C++中,由于使用cout等流對象進行的輸出語句實際上也是一個表達式,所以對于如下常見的打印整個數組的值的代碼:
for (i = 0; i < size; ++i)
cout << a[i] << endl;
使用逗號運算符并利用好自加運算的特性,可以簡寫為:
for (i = 0; i < size; cout << a[i++] << endl) ; /* 注意分號不能少 */
而對于打印一個二維數組這樣的操作,由于循環完一行之后要輸出換行,所以外層循環(遍歷每一行)不得不使用復合語句:
for (i = 0; i < size; ++i)
{
for (j = 0; j < size; ++j)
cout << a[i][j];
cout << endl;
}
但如果把cout移到循環內,就可以顯著減少行數:
for (i = 0; i < size; cout << endl; ++i)
for (j = 0; j < size; cout << a[i][j++]) ; /* 注意分號不能少 */
當然,也可以是
for (i = 0; cout << endl, i < size; ++i)
for (j = 0; cout << a[i][j], j < size; ++j) ; /* 注意分號不能少 */
但使用逗號運算符時一定要注意其隱含的不確定性,如表達式:
++i, cout << a[i], x + y;
如果語言中對各個表達式的求值順序不確定,那么cout的子表達式所輸出的a[i]就無法確定是自加以前的i還是自加以后的i. 使用逗號運算符,以及相關的重載運算符的連續表達式時應當格外注意這一點。
注:由于時間倉促,本文程序片斷未經調試,如有錯誤,歡迎批評指正。
原文轉自:http://www.anti-gravitydesign.com