本文引用地址:http://dyxdggzs.com/article/201611/322385.htm函數指針的建議和技巧
有些函數指針的應用技巧。
使用指定空間的指針
把函數指針從一個(gè)普通的指針變成一個(gè)指定空間的指針。用一個(gè)字節保存指針。因為函數屬于CODE存儲區(在8051里),一個(gè)字節可以用來(lái)保存聲明的函數指針作為CODE指針。例如:
void (code *function_ptr) (void) = another_function;
如果你選擇在你的函數指針聲明中包含code關(guān)鍵字,就可以在任何地方使用它。如果你聲明一個(gè)函數,它接收一個(gè)3字節的普通指針,通過(guò)指定空間傳遞,2字節函數指針,壞事將要產(chǎn)生。
再入函數和指針
Keil C51 為函數的再入提供關(guān)鍵字“reentrant”。再入函數的參數通過(guò)模擬棧來(lái)傳遞。模擬棧對于small存儲模式位于IDATA,對于compact存儲模式位于PDATA,對于large存儲模式位于XDATA。如果你使用再入函數,在STARTUP.A51中你必須初始化再入棧的指針。參考下面的啟動(dòng)代碼:
;----------------------------------------------------------------------
;Reentrant Stack Initilization
;
;The following EQU statements define the stack pointer for reentrant
;functions and initialized it:
;
;Stack Space for reentrant functions in the SMALL model.
IBPSTACKEQU0; set to 1 if small reentrant is used.
IBPSTACKTOPEQU0FFH+1; set top of stack to highest location+1.
;
;Stack Space for reentrant functions in the LARGE model.
XBPSTACKEQU0; set to 1 if large reentrant is used.
XBPSTACKTOPEQU0FFFFH+1; set top of stack to highest location+1.
;
;Stack Space for reentrant functions in the COMPACT model.
PBPSTACKEQU0; set to 1 if compact reentrant is used.
PBPSTACKTOPEQU0FFFFH+1; set top of stack to highest location+1.
;----------------------------------------------------------------------
你必須設置你使用的存儲模式的堆棧和設置棧頂。當有入棧時(shí),再入函數的棧指針減少(向下移動(dòng))。為了保護內部的數據區,有一個(gè)技巧就是把所有的再入函數放在一個(gè)獨立的存儲模式,像large或compact。
用reentrant聲明再入函數。
void reentrant_func (long arg1, long arg2, long arg3) reentrant
{
}
用large和reentrant聲明一個(gè)large模式的再入函數。
void reentrant_func (long arg1, long arg2, long arg3) large reentrant
{
}
聲明一個(gè)再入函數的函數指針,必須使用reentrant關(guān)鍵字。
void (*rfunc_ptr) (long, long, long) reentrant = reentrant_func;
再入函數的函數指針和非再入函數的函數指針沒(méi)有許多不同。當使用再入函數指針時(shí),會(huì )生成更多的代碼,因為參數被壓入模擬棧。然而,沒(méi)有特殊的連接要求和不需要打亂“OVERLAY”指令。
如果通過(guò)間接調用傳遞超過(guò)3個(gè)參數給函數,需要再入函數指針。
使用再入指針的注意事項
keil中的函數遞歸調用可分為兩種情況,一種是普通函數遞歸,調用時(shí),新調用函數的程序儲存空間覆蓋原來(lái)的相同函數調用的程序儲存空間,使得原來(lái)的局部變量消失了;還有一種是再入函數(用reentrant說(shuō)明)的遞歸,每次遞歸,keil為再入函數生成一個(gè)模擬棧,再入函數參數和局部變量被放在這模擬棧中,這樣使得原來(lái)調用函數的局部變量就沒(méi)有消失了,而新的調用函數參數和局部變量又可以繼續。
再入函數的定義:
函數類(lèi)型 [reentrent] 函數名 (形式參數)
例如:int [reentrent]fution(char n)
{if(n<1)return(1);
else return(n*fution(n-1));
}
使用再入函數注意事項:
1: 再入函數不能傳送bit類(lèi)型的參數,函數內部也不能定義局部位變量,不能有位操作??傊c位有關(guān)的定義和操作在再入函數中都不能實(shí)現。
2:同一程序中可以有不同儲存模式的再入函數,但是注意,任意模式的再入函數不能調用不同儲存模式的再入函數,但可以調用不同儲存模式的非再入函數。
3參數傳遞上,實(shí)際參數可以傳遞給間接調用的再入函數;非再入函數不能包含調用參數,因為那樣會(huì )覆蓋了原來(lái)的參數;但是,可以用全局變量來(lái)進(jìn)行參數傳遞。
總結
函數指針是非常有用的,并不是很困難的,如果你注意連接調用樹(shù),保證用“OVERLAY”指令修正一些沖突。
評論