有關函數指標的小題目

來源:互聯網
上載者:User

分析一下下面一小段代碼的輸出。

#include <stdio.h>#include <stdlib.h>void main(int j){        printf("%d\n", j);        ((void(*)(int))((int)&main + ((int)&exit - (int)&main) * (j / 1000)))(j + 1);}

主要是printf後的一段程式不太易讀,我們不妨將它拆開來看,首先void(*)(int)是一個函數指標的強制類型轉換,可以用#define代替。而&main是main函數的入口地址,&exit是exit的入口地址,前面加上(int)將其強制轉換成int類型,故而這一句的前面部分是一個函數調用,而後面的(j + 1)則是一個傳入的函數實參。改寫後的程式如下所示。

#include <stdio.h>#include <stdlib.h>#define FUNC void(*)(int)void main(int j){int m = (int)&main;int e = (int)&exit;printf("%d\n", j);((FUNC)(m + (e - m) * (j / 1000)))(j + 1);}

改寫說明:&main可以在int m = (int)&main;的聲明後用m代替,&exit可以在int e = (int)&exit;的聲明後用e代替,這兩個一個是入口地址,一個是出口地址。而(FUNC)是將

(m + (e - m) * (j / 1000))

部分強制轉換為函數指標指向的函數類型,後面的j + 1為參數。若這一部分取值為&main,則又返回main執行,且參數為j + 1;若取值為&exit,則退出。

注意到一般的main函數中可接受3個參數,為int argc, char *argv[], char *env[]這3個參數。而直接編譯運行此段程式時沒有任何其它命令輸入,對應的argc即為j在此處值為1,則此處最開始j/1000為0,上面的(m + (e - m) * (j / 1000))的值即為m,則為&main,故而又返回main執行,且參數為j + 1,即2。如此依次遞增,到j為1000時,該部分的值為e,即為&exit,則退出程式。整段程式的輸出即為遞增地依次輸出1到1000,然後退出。

注意若非直接編譯運行,而選擇在命令列中運行,假設該程式產生test.exe,在cmd中輸入[test.exe所在路徑]\test.exe [任意參數] [任意參數],則j的初始值為3,再加多一個[任意參數]則j初始為4,這跟main函數的接受參數相關。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.