Re: [問題] 函式指標
剛才翻了一下精華區和以前的文章,好像要不是有點錯(以標準來說)就是沒
有回答到。所以打了這一篇。
※ 引述《Nairoda (new)》之銘言:
: 有兩個問題請教各位
: 第一個問題:
: 若宣告一個函式指標變數且將一個函數賦值給它,
: 那此函式指標變數指向何處? 像是指向一個記憶體位址嗎?
: 而記憶體儲存的是函數?
: ex:
: duoble ex1(double x);
: int main(){
: double (*pf)(double);
: pf = ex1;
: }
: ex1 是函式名稱, 亦代表一個函式的位址, 所以可以寫 pf = ex1;
: 那函式 ex1 本身是儲在何處? 是像一般變數一樣存在記憶體中嗎?
不一定。在 C 裡面,函式不是物件,是屬於另一個世界的東西。它的表示法
也不受一般物件的限制(一般物件的表示法必須是一連串的位元或位元組),所以
連要「儲存」什麼可能都講不清楚。你家電腦很有可能選擇把程式碼擺在記憶體某
一塊,但像哈佛計算機結構就把程式和資料擺到不同的記憶體去了。
那函式指標是什麼呢?我舉個很爛的例子好了:很久以前我們要寫一個目標語
言竟然沒有 jump 的編譯器,所以只好自己記一張表格,然後用表格中的位置充當
函式指標。指標不一定要是你家電腦的記憶體位置。反正只要是某種可以指東西的
方法就好了。除了少數規定的狀況外,不同型態的指標的表示法可能都不一樣,函
式指標的表示法當然也可以自己亂定。值得一提的是,除了特別規定的狀況外,標
準不保證指向物件的指標可以轉型成指向函式的指標,反過來當然也不保證。這都
是因為函式完全是另一個世界的產物,跟物件一點關係也沒有,指向他們的方法自
然也可以完全不同。
: 第二個問題:
: 以下例子中有兩個函式 f1 與 f2, 其第一個形式引數皆是同型的函式指標,
: 且回傳第一個引數所計算出來的數值。請問以下例子中 return 的寫法
: 有無差異? (雖然傳回的數值都是一樣的)
: #include<stdio.h>
: double f1(double (*pfun)(double), double x);
: double f2(double (*pfun)(double), double x);
: double sqr(double x);
: int main(){
: printf("f1(sqr,2.0) = %lf\n",f1(sqr,2.0));
: printf("f2(sqr,2.0) = %lf\n",f2(sqr,2.0));
: }
: double f1(double (*pfun)(double), double x){
: return pfun(x);
: }
: double f2(double (*pfun)(double), double x){
: return (*pfun)(x);
: }
完全沒有差別。跟陣列指標自動轉型類似(見別篇文章),一個代表函式的東
西(function designator 有好翻譯嗎)除了在極少數的狀況下,都會自動轉型成
指向該函式的指標。實際上就算你寫...
| double f16 (double (*pfun) (double), double x) {
| return (* * * * * * * * * * * * * * * * pfun)(x);
| }
也無所謂。慢動作解析(精神上的)運算是這樣的:首先 * 運算子會從函式
指標算出一個代表函式的東西,可是下一步又馬上被轉型成指標。再經過一次 *
運算子,再轉型一次。不管經過多少次 * 都會被自動轉型再轉回指標。世上最無
用的掙扎莫過於此 xDDD(這只是精神上這樣算,實際上編譯器當然不會這麼笨。
很有可能上面三個函式會產生一模一樣的機械碼。)
以下兩段英文是給想看標準的人看的:
| A function designator is an expression that has function type.
| Except when it is the operand of the sizeof operator 54) or the
| unary & operator, a function designator with type "function
| returning type" is converted to an expression that has type
| "pointer to function returning type".
@ C99 6.3.2.1 / 4
| 54) Because this conversion does not occur, the operand of the
| sizeof operator remains a function designator and violates
| the constraint in 6.5.3.4.
@ C99 footnote
: double sqr(double x){
: return x*x;
: }
: 請多多指教.
希望有回答到你的問題。同場加映:其實這樣寫也是可以的:
| double f1 (double pfun(double), double x) {
| return pfun(x);
| }
因為編譯器會自動「調整」你的函式宣告,變成和這等價:
| double f1 (double (*pfun)(double), double x) {
| return pfun(x);
| }
理由是因為自動轉型無所不在,所以別人也沒辦法傳函式給你(立刻轉型成
函式指標),區分兩者也就沒什麼意義啦!要用哪一個純粹看你的寫作風格。以
下給想看標準的人:
| A declaration of a parameter as "function returning type" shall
| be adjusted to "pointer to function returning type", as in 6.3.2.1.
@ C99 6.7.5.3 / 8
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.30.39
※ 編輯: Favonia 來自: 140.112.30.39 (07/30 05:37)
推
07/30 05:46, , 1F
07/30 05:46, 1F
→
07/30 08:45, , 2F
07/30 08:45, 2F
※ 編輯: Favonia 來自: 140.112.30.39 (07/30 09:20)
※ 編輯: Favonia 來自: 140.112.30.39 (07/30 09:21)
推
07/30 10:13, , 3F
07/30 10:13, 3F
推
07/30 10:30, , 4F
07/30 10:30, 4F
推
07/30 19:42, , 5F
07/30 19:42, 5F
推
01/13 11:15, , 6F
01/13 11:15, 6F
討論串 (同標題文章)