函數指標的另類用法 from . Andrews

來源:互聯網
上載者:User
我曾經和一些人聊過天,他們那時在書寫在一個小型的微處理器上單機啟動並執行C程式。當這台機器的開關開啟的時候,硬體會調用地址為0處的子程式。

為了模仿電源開啟的情形,我們要設計一條C語句來顯式地調用這個子程式。經過一些思考,我們寫出了下面的語句:
(*(void(*)())0)();
這樣的運算式會令C程式員心驚膽戰。但是,並不需要這樣,因為他們可以在一個簡單的規則的協助下很容易地構造它:以你使用的方式聲明它。

每個C變數聲明都具有兩個部分:一個類型和一組具有特定格式的期望用來對該類型求值的運算式。最簡單的運算式就是一個變數:

float f, g;
說明運算式f和g——在求值的時候——具有類型float。由於待求值的時運算式,因此可以自由地使用圓括弧:
float ((f));
則表示((f))求值為float並且因此,通過推斷,f也是一個float。
同樣的邏輯用在函數和指標類型。例如:

float ff();

表示運算式ff()是一個float,因此ff是一個返回一個float的函數。類似地,

float *pf;表示*pf是一個float並且因此pf是一個指向一個float的指標。
這些形式的組合聲明對錶達式是一樣的。因此

float *g(), (*h)();

表示*g()和(*h)()都是float運算式。由於()比*綁定得更緊密,*g()和*(g())表示同樣的東西:g是一個返回指float指標的函數,而h是一個指向返回float的函數的指標。

當我們知道如何聲明一個給定類型的變數以後,就能夠很容易地寫出一個類型的模型(cast):只要刪除變數名和分號並將所有的東西包圍在一對圓括弧中即可。因此,由於

float *g();聲明g是一個返回float指標的函數,所以(float *())就是它的模型。

有了這些知識的武裝,我們現在可以準備解決(*(void(*)())0)()了。 我們可以將它分為兩個部分進行分析。首先,假設我們有一個變數fp,它包含了一個函數指標,並且我們希望調用fp所指向的函數。可以這樣寫:
(*fp)();
如果fp是一個指向函數的指標,則*fp就是函數本身,因此(*fp)()是調用它的一種方法。(*fp)中的括弧是必須的,否則這個運算式將會被分析為*(fp())。我們現在要找一個適當的運算式來替換fp。

這個問題就是我們的第二步分析。如果C可以讀入並理解類型,我們可以寫

(*0)();
但這樣並不行,因為*運算子要求必須有一個指標作為他的運算元。另外,這個運算元必須是一個指向函數的指標,以保證*的結果可以被調用。因此,我們需要將0轉換為一個可以描述“指向一個返回void的函數的指標”的類型。
如果fp是一個指向返回void的函數的指標,則(*fp)()是一個void值,並且它的聲明將會是這樣的

void (*fp)();

因此,我們需要寫

void (*fp)();
(*fp)();

來聲明一個啞變數。一旦我們知道了如何聲明該變數,我們也就知道了如何將一個常數轉換為該類型:只要從變數的聲明中去掉名字即可。因此,我們像下面這樣將0轉換為一個“指向返回void的函數的指標”
(void(*)())0
接下來,我們用(void(*)())0來替換fp:
(*(void(*)())0)();
結尾處的分號用於將這個運算式轉換為一個語句。
在這裡,我們就解決了這個問題時沒有使用typedef聲明。通過使用它,我們可以更清晰地解決這個問題:
typedef void (*funcptr)();
(*(funcptr)0)();

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.