瀏覽看雪論壇,發現有人講了一個有趣的C語言程式。

我做了一點點的修改,最後打印出 i O y(中間那個是個心的形狀,執行程式就知道了)

#include

int main()

{

const short int c1 = 49920;

const int c2 = 1073742008;

int (*pf)() = (int (*)())&c2;

printf(“%c %c %c\n”, *((char*)pf()+1)-0x11,*(char*)pf()-0x4a, *((char*)pf()+1)-0x1);

return 0;

}

這兩句程式碼:

const short int c1 = 49920;

const int c2 = 1073742008;

定義了兩個區域性變數,數值轉換成16進製為:

const short int c1 = 0xc300;

const int c2 = 0x400000b8;

其中變數c1的地址為:0x0012FF44 ,佔兩個位元組,c2的地址為:0x0012FF40,佔四個位元組。

這兩個變數佔據了連續的空間。變數賦值後,從0x12fff40開始的記憶體單元儲存的位元組碼為:B8 00 00 40 00 C3 。對應的彙編碼是:

mov eax,400000h

ret

一個有趣的C語言程式,誰說程式設計師不懂浪漫

用OD試試,輸入二進位制程式碼或者彙編程式碼就可以看到

接下來的這句:

int (*pf)() = (int (*)())&c2;

定義了一個函式指標,引數為NULL,返回值為int型別。 這個函式指標,指向上面的彙編碼(注意記憶體地址的順序)。這樣,後面執行pf(),就執行了這段彙編碼。

接下來,

printf(“%c %c %c\n”, *((char*)pf()+1)-0x11,*(char*)pf()-0x4a, *((char*)pf()+1)-0x1);

先看*(char*)pf()-0x11這個表示式, 執行了了pf指向的彙編程式碼,從彙編程式碼看,這個函式呼叫後的返回值是0x400000,pf()前面的char *是把函式的返回值轉換成一個char*型指標,這個指標指向0x400000,前面再加個*號,表示取0x400000地址的內容,由於是char *型指標,因此從這個地址取一個位元組。

*(char*)pf()-0x11 表示的是從0x400000取出的位元組內容再減去0x11。

熟悉PE檔案結構的朋友一定知道,對於exe檔案0x400000是記憶體載入的基地址。也就是說,0x400000 位元組的內容對應的是0x4D,0x400001 位元組的內容對應的是0x5A。

這是我們常說的pe檔案起始的兩個位元組,“MZ”。這樣,表示式*(char*)pf()-*就可以隨意修改了。

一個有趣的C語言程式,誰說程式設計師不懂浪漫

送給女朋友做個禮物吧。

一個有趣的C語言程式,誰說程式設計師不懂浪漫

沒事的時候可以瀏覽些論壇,經常能發現一些很多有趣的東西,很多時候這些不經意的發現,往往增加了生活的樂趣。這個帖子比較早了,一開始看到這個程式也沒想明白,看了一下解釋才豁然開朗,當然這種程式碼在實際中是不可能使用的,不過我倒是很喜歡蒐集這些稀奇古怪的小程式碼,平添了生活的樂趣。

——————————-

學習從來不是一個人的事情,要有個相互監督的夥伴,工作需要學習C/C++或者為了入行、轉行學習C/C++的夥伴可以私信回覆小編“學習”領取全套免費C/C++學習資料、影片