PHP 7.1 對 list() 語法做了一些調整,讓 list() 操作使用起來更簡便。
原本的 list() 語法:
list($a, $b) = [1, 2];
// $a = 1, $b = 2
在 7.1 以後可以使用陣列來表示:
[$a, $b] = [1, 2];
這個語法稱為 Symmetric Array Destructuring。
有了這個 feature 以後,不用另外宣告暫存變數也可以對調變數 (swap):
[$b, $a] = [$a, $b];
PHP 7.1 對 list() 語法做了一些調整,讓 list() 操作使用起來更簡便。
原本的 list() 語法:
list($a, $b) = [1, 2];
// $a = 1, $b = 2
在 7.1 以後可以使用陣列來表示:
[$a, $b] = [1, 2];
這個語法稱為 Symmetric Array Destructuring。
有了這個 feature 以後,不用另外宣告暫存變數也可以對調變數 (swap):
[$b, $a] = [$a, $b];
最近在 refactor legacy code,遇到很尷尬的函式定義,笑也不是哭也不是。
函式會要求使用者傳入多個參數,有時並不是所有的參數都必須給值,函式的設計者會以大家較常使用的方式來當作參數的預設值,例如 PHP 裡面的「json_decode()」:
json_decode($json); // consider as json_decode($json, false)
json_decode($json, true); // 不使用預設值才手動傳數第二個參數
但這次遇到比較尷尬的是,legacy code 把第一個參數設計為 optional,也就是有預設值。但問題來了,在 PHP 的語法當中,呼叫函式無法在前幾個參數不給值:
getData( , 'some', 'option'); // syntax error
所以不管怎麼樣,都至少要給第一個參數:
getData(null, 'some', 'option');
所以把有預設值的參數放在前面其實根本沒有省下什麼時間呀 … XD
查資料時,無意間發現 Google 有一系列的演講,整理出如何撰寫乾淨、好維護、可以測試的程式碼。
影片有很多段,已查不到播放順序,請各位自己挑選了看。
無意間發現透過 printf 輸出資料時,程式會將資料放在 buffer 中,過一段時間後再一起印出。
int main(){
while(1){
printf(".");
sleep(1);
}
return 0;
}
可以透過 fflush() 強制將 buffer 中的資料輸出:
while(1){
printf(".");
fflush(stdout);
sleep(1);
}
前陣子某 geek 朋友過生日,所以想用程式給他一個小驚喜。原本打算送給他一個假的 patch,讓他在編譯時收到訊息,不過弄半天還是沒搞懂 #pragma 怎麼用,後來改用程式碼混淆的方式製作卡片。
步驟大概如下:
卡片就是 ASCII art 畫一下,看得出來是生日祝賀就好 XD
畫好後,找個方法轉成 C 語言。看了看內容,發現全部都是由「-」、「/」等幾個字元組成,所以要用程式畫出來只要控制要印出的字元以及迴圈次數即可。這時先假設有個函式叫做 pt() ,傳入二個參數,一個是使用的字元,一個是重複次數:
void pt( int ascii, int count ){
int i;
for( i = 0; i < count; i++ ){
printf("%c", ascii);
}
}
按照順序計算字元重複次數以後,就可以把卡片轉換成程式:
#include <stdio.h>
void pt(int ascii, int count){
if( count > 0 ){
printf("%c", ascii);
pt( ascii, count-1 );
}
}
int main(){
pt(10, 1); // n
pt(32, 23); // sapce
pt(47, 1); // "/"
pt(92, 1); // ""
pt(32, 23);
pt(47, 1);
.....
return 0;
}
接下來開始製造大亂。
平常都在找讓程式碼可讀性增加、降低維護成本的方法,反而要倒過來就不太會了,好在之前 CoolShell.cn 上看到一篇文章「如何写出无法维护的代码」,有個方法可以參考。
先來處裡比較簡單的,程式碼中數字只要執行時期表達方式在執行時期的結果相同即可,所以可以把 pt() 參數的數字改成 16 進位,或是用運算式改寫。
pt(0xA, 10+8-17); // n
main() 中 pt() 重複次數太高,即使取代名稱以後看起來還是井然有序。所以複製出多個功能完全一模一樣的函式,並且建立另一個函式專門呼叫 printf。
void pt( int ascii, int count ){
if( count > 0 ){
printChar( ascii );
pt( ascii, count-1 ); // Can call pt2() and other, too
}
} ;
void pt2( int ascii, int count ){ ... } ;
void pt3( int ascii, int count ){ ... } ;
void pt4( int ascii, int count ){ ... } ;
void printChar( int ascii ){
printf("%c", ascii );
}
隨機把 main() 中的函式呼叫名稱換掉以後就差不多夠亂了,最後把變數名稱、函式名稱隨便換一下就大功告成了。
後來看了 IOCCC 和 Just Another Perl Hacker 後,覺得實在還太嫩,以後誰生日再來找其他方法惡搞 XD
後記:
gcc -S 參數可以將 C 語言轉成組合語言:
gcc -S -o code.asm source.c
Javascript 有現成的工具可以玩:aaencode!