問題:當計算機啟動時,硬體将調用首位址為0的子例程,為了模拟開機啟動時的情形,如何設計出一個c語句,以顯示調用該子例程。
換個問法:有一段程式存儲在起始位址為 0的一段記憶體上,如果我們想要調用這段程式,請問該如何去做?
《c陷阱與缺陷》給出答案:(*(void(*)())0)();
相關知識:函數指針
函數指針是指向函數的指針變量,即本質是一個指針變量。
在C語言中規定,一個函數總是占用一段連續的記憶體區,而函數名就是該函數所占記憶體區的首位址。我們可以把函數的這個首位址(或稱入口位址)賦予一個指針變量,使該指針變量指向該函數。然後通過指針變量就可以找到并調用這個函數。我們把這種指向函數的指針變量稱為“函數指針變量”,簡稱:函數指針
指向函數的指針包含了函數的位址,可以通過它來調用函數。聲明格式如下:
類型說明符 (*函數名)(參數)
其實這裡不能稱為函數名,應該叫做指針的變量名。這個特殊的指針指向一個傳回整型值的函數。指針的聲明必須和它指向函數的聲明保持一緻。
問題分析:
1、想要調用這段程式(子例程),設為func函數,由上述相關知識,我們可以使用最基本的指針函數void(*f) ()來調用子例程,調用方法:(*func)();
2、子例程存儲在起始位址為 0的一段記憶體上,故可了解為0是這個子例程的入口位址,func函數入口位址為0。即func指向位址為0的函數;
3、由2知,func為指向位址0的函數,是以func是一個函數指針,設func是一個指向傳回值為void類型的函數的指針,故可設func的函數指針聲明為void (*pfunc)();
4、由函數聲明void (*pfunc)()類比于變量聲明,同樣,通過強制轉換,我們可以得到位址為0的入口函數位址(void (*)())0;
5、将4代入1中,即有(*(void (*)())0)().
其他:
指針函數:
一個函數不僅可以帶回一個整型資料的值,字元類型值和實型類型的值,還可以帶回指針類型的資料,使其指向某個位址單元。
傳回指針的函數,一般定義格式為:類型辨別符 *函數名(參數表)
示例:int *f(x,y);
函數指針是一個指向函數的指針,而指針函數隻是說明他是一個傳回值為指針的函數。
void* 指針:
c++提供了一種特殊的指針類型void*,它可以儲存任何對象類型的位址(c++ primer)。
參考:http://lionwq.spaces.eepw.com.cn/articles/article/item/18258
http://blog.csdn.net/norbe/article/details/624257