typedef void (*pFunction)(void);
JumpAddress = *(__IO uint32_t*) (DEF_FLASH_AppStartaddr + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) DEF_FLASH_AppStartaddr);
Jump_To_Application();
對函數指針有了初次見面。未能理解,現在做簡要分析。
1、定義一個指向unsigned char 型的指針:如 unsigned char *p;
2、將一個指針轉化成指向unsigned char型數據的指針,如:(unsigned char*)p;
3、定義一個類型,該類型為int,並定義一個指向該類型的指針p如, typedef int INT_Typedef; INT_Typedef *p;
4、定義一個函數指針,該函數無參數,無返回值。typedef void (*Func)(void);
typedef 的作用是把已知的類型定義新類型,所以新類型(*Func)(void)的返回值是void。如常見的main(),括號內是main的參數,所以該函數指針指向的函數無形參。其次(*Func)等同於main的地位。所以 Func就是函數指針了。
綜上所述就可以理解 typedef void (*pFunction)(void),是定義了一個新類型,該類型是一個函數指針,它指向的函數的形參為void,返回值為void。
如果要指向有參數或者有返回值的函數,則適當修改void的類型的可以了。如果進行定義和初始化應該為:pFunction pFun = &main;當然實際設計中不會將main函數賦值給其他人,這里只是讓人清楚的知道main是個函數名而已。
5、誤寫成typedef (void*) Func(void),則應該解釋為,定義了一個新類型,該類型名為Func,Func是一個函數而不是函數指針,該函數的參數為void,返回值是指向void的指針。如果賦值應為:extern void * Func1(void)(); Func fun = Func1;
整理來源:http://zhidao.baidu.com/link?url=lYBzk1BiYAVy20H4HBOXqAC70E0o616Z0HvvOQeP-2PCoFTjTWZXr-_c1At2OyfyULfUPD4BkVbOFtLSDdzH7q
void (*p)()是一個指向函數的指針,表示是一個指向函數入口的指地變量,該函數的返回類型是void類型。它的用法可參看下例: 例如:有一返加void值的函數swap,(swap用來交換兩個數) void (*p)(); /*定義指向函數的指針變量p*/ p=swap; /*使指針變量p指向函數max*/ (*p)(a,b); /*通過指針變量p調用函數max*/ 它等價於: swap(a,b) void *p()是一個指針型函數,它的函數名為p,返回了一個指針,因為是void,這個指針沒有定義類型,所以返回的是一個通用型指針。 給你舉一個例子: #include<stdio.h> int *max(int *p); void main() { int a[10]={96,23,45,86,79,63,58,36,29,95}; int *p; p=max(a); printf(“max=%d\n”,*p); } int *max(int *p) { int i,*q=p; for(i=1;i<10;i++) if(*(p+i)>*q) q=p+1; return q; }
整理自:http://www.cnblogs.com/leon3000/archive/2007/11/15/2037989.html
void (*b[10]) (void (*)());
void (*b[10]) (void (*)());
看到這行代碼,相信程序員們都會倒吸一口冷氣吧。如果非常不幸的在維護的代碼中看到類似的表述,除了想辦法找出寫出這種天書的猛人來,只能自己硬着頭皮搞清楚了。
在C和C++中,構造這類聲明表達式只有一條簡單的規則:按照使用的方式來聲明。
C變量的聲明都是由兩部分組成的:類型,以及一組類似表達式的聲明符(declarator)。聲明符類似於表達式,對它求值應該返回一個聲明中給定類型的結果。例如,我們來看一個簡單的聲明:
float f;
這里f就是聲明符,對其求值,應該得到一個float型的數值。
然后看括號的作用,比如:
float ((f));
很簡單,這個聲明的含義就是,((f))的類型為浮點類型。因為括號和f之間沒有其他的修飾了,所以,我們可以推知,f也是浮點型。
再來看稍微復雜點的:
float f();
我們注意到有一個()表達式出現,這個聲明符的含義是一個函數。所以這個聲明的含義就是,f()的求值結果是一個浮點數,也就是說,f是個返回值為浮點數的函數。
OK,這些都很簡單,再看一個:
float *f();
這個就是表示*f()是個浮點表達式,而()的結合優先級高於*,所以,*f()也就是*(f()),f是個函數,返回值是個指針,這個指針指向一個浮點數。
如果*f是先結合的呢?比如:
float (*f)();
這時,f就不是和()結合而成為一個函數名,而是和*結合成為一個指針名,這個指針,是指向函數入口的函數指針,而這個函數,返回值是浮點型。
現在我們知道怎么聲明一個指定類型的變量了。在這個聲明表達式中,把變量名,和聲明末尾的分號去掉,剩余的部分用一個括號整個括起來,這樣就得到了這個變量的類型聲明了,比如:
float (*f)();
這個表示f是一個指向返回值為浮點型的函數指針。而我們把f這個變量名,和最后的;號去掉,就得到:
( float (*)() )
這個就表示,這個表達式是一個類型,即“指向返回值為浮點型的函數的指針”。如果用這個類型去修飾一個變量名,我們就叫它類型轉換符。
現在有了這些預備知識,我們可以回頭看標題的聲明到底是什么意思了:
void (*b[10]) (void (*)());
首先,表達式的后半部分被兩個()分隔開了,我們分別分析它們。( *b[10] ),其中出現了變量名b,很容易就知道,b是一個有10個元素的數組,每個元素都是一個指針。
然后,看(void(*)()),其中沒有出現變量名,所以它代表了一個類型,即“指向返回值為void型的函數的指針“,而我們知道,C語法中,類型修飾符是必須出現在變量名的左邊的,而在整個表達式中這個類型符是在變量名b的右邊,所以, (void(*)())最外層的這個(),表示了定義了一個函數,這個函數有一個參數,就是一個指針,具體來說,就是“指向返回值為void型的函數的指針“。
這樣就很清楚了,b數組里,每一個指針元素,都是一個函數指針,這個函數有一個參數,這個參數是一個函數指針。整個表達式最左邊的void,則定義了b數組中函數指針所指向函數的返回值類型。
在一串繞口令式的解說后,我們終於看到了事實的真相:這行代碼就是逗你玩...
如果不是故意偷懶,這樣代碼的作者真是在玩弄閱讀者的感情,如果非要實現這樣一個復雜的定義的話,我們也是有更好的方法的,就是使用typedef來進行類型聲明。
在面對void (*b[10]) (void (*)());時,我們可以先聲明后半部分的類型:
typdef void (*pFunParam)();
即表示,類型pFunParam,是一個函數指針。
然后,針對整個表達式聲明一個類型:
typedef void (*pFun)(pFunParam);
即表示,類型pFun,是一個函數指針。此函數的參數類型為pFunParam。
最后,進行變量的聲明:
pFun b[10];
這樣,就清晰許多了吧。最重要的時,利用這樣的方式,將編寫者的設計思路也體現在了代碼中。
最后,介紹一個更快速的閱讀方法:從右向左。
編譯器在進行代碼掃描時是從左向右的,而我們在解讀這個表達式的時候,從右向左的方法會更容易些,如:
從右向左掃描以上表達式,首先我們看到一個“)”,因為其右邊再沒有變量,所以我們知道這是一個函數定義,然后,又看到一對“()“,顯然也是函數定義,在就是(*),顯然和后面的()聯合起來表達了一個函數指針,再左邊的void,即修飾了此指針的類型;然后出現了和最右邊”)"對應的”(”,顯然這個函數定義也完成了,再左邊的[10]表達了一個數組,左邊是它的名字b,而更左邊的“*”和后面的“(“一起表達了一個函數指針,這個函數指針定義了b數組中元素的類型。再往左,指針元素的定義void也出現了。這樣,我們就又看到了此表達式的真相。