Re: [問題] 函式指標

看板C_and_CPP作者 (小西風最乖了*^^*)時間12年前 (2011/07/30 05:29), 編輯推噓5(501)
留言6則, 6人參與, 最新討論串2/2 (看更多)
剛才翻了一下精華區和以前的文章,好像要不是有點錯(以標準來說)就是沒 有回答到。所以打了這一篇。 ※ 引述《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
C99 真是博大精深... 好文推一下...
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
多謝 F 大的優文, 再一次長知識.
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
文章代碼(AID): #1ECoOqLM (C_and_CPP)
討論串 (同標題文章)
本文引述了以下文章的的內容:
問題
2
12
完整討論串 (本文為第 2 之 2 篇):
問題
2
12
文章代碼(AID): #1ECoOqLM (C_and_CPP)