C語言的複雜程度絕對令人難以想象,同時由於一些特殊的原因,C裡面同時存在
一些讓人糾結的特性。
下面我們看一些有趣的C語言代碼。
Exp:
main(){ printf(&unix["\021%six\012\0"], (unix)["have"] + "fun" - 0x60);}
第一步:
對於這樣的代碼要理解首先要做的是進行縮排,縮排後如下所示:
main(){ printf( &unix["\021%six\012\0"], (unix)["have"] + "fun" - 0x60);}
如上面所示,還是不好理解,我們可以在縮排一下:
main(){ printf( &unix["\021%six\012\0"], /
(unix)["have"] + "fun" - 0x60);}
第二步:
從上面縮排後的代碼以及printf函數的函數原型:
size_t printf(const char *format,...);
我們知道在上面的代碼中:
const char *format= &unix["\021%six\012\0"]
而我們的第一個可變參數為:
va_list[1]=(unix)["have"] + "fun" - 0x60); //這裡簡單的假設可變參數為一個數組型,具體可參與K&R的教程
接下來我們分析:
format指標; 在unix系統中, 有一個預設的定義,那就是:
#define unix 1
因此可以知道
*format= &unix["\021%six\012\0"]=&"\021%six\012\0"[1]
=&("\021%six\012\0"[1]) //這裡表示指標的指向這個地方與&array[i]同樣理解
這樣可以知道:
*format="%six\012\0"="%six\021\0"
第三步:
分析(unix)["have"] + "fun" - 0x60可知:
(unix)["have"] + "fun" - 0x60= "have"[unix]+ "fun" - 0x60
="have"[1]+ "fun" - 0x60
='a'+ "fun" - 0x60
=97+ "fun" - 0x60
=97+ "fun" - 96
= "fun" +1
第四步:合并
將上面的*format和...可變參數合并,並用printf函數輸出,則可以得到:
printf("%six\021\0","fun" +1);
這裡以:
%s 輸出 "fun"+1為地址的字串, 因此輸出: un
而
format 中的 ix\021\0 則輸出 ix
因此合并起來輸出的就是:
unix
我發現國內很多的教材對這裡用到的很多知識點都沒有透徹的說明,這其中當然包括我們大學
裡面很多老師推薦的譚的教程,為了很好的理解C建議還是看看外國人寫的書,畢竟C是老外發明的,
而且在翻譯的過程中很多話很難找到完全一致的漢字來表示英語單詞。
這就是: 英語比漢語更適合描述科技。 //不是我說的, 大家可以想想是不是這樣。
不多說了,鑒於我的C語言水平實在有限,上面的分析難免有錯誤,歡迎各位大俠彎腰找板磚,