<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > Keil C51 中的函數指針和再入函數

Keil C51 中的函數指針和再入函數

作者: 時(shí)間:2016-11-27 來(lái)源:網(wǎng)絡(luò ) 收藏
概述

函數指針是C語(yǔ)言中幾個(gè)難點(diǎn)之一。由于8051的C編譯器的獨特要求,函數指針和再入函數有更多的挑戰需要克服。主要由于函數變量的傳遞。

本文引用地址:http://dyxdggzs.com/article/201611/322385.htm

典型的(絕大部分8051芯片)函數變量通過(guò)堆棧的入棧和出棧命令來(lái)傳遞。因為8051只有有限的堆??臻g(128字節或更少的64字節),函數變量必須通過(guò)不同的方式進(jìn)行傳遞。

8051的PL/M-51編譯器,介紹在固定的存儲空間存儲變量的方式。當使用連接器時(shí),程序建立一個(gè)調用樹(shù),計算出函數變量的互斥空間,然后覆蓋它們。這就是連接器的“OVERLAY”指令。

因為PL/M-51不支持函數指針,所以不能實(shí)現間接函數調用。然而,C語(yǔ)言中存在這樣的問(wèn)題。連接器知道哪塊空間用于存儲間接函數的變量。怎樣間接加入函數進(jìn)入調用樹(shù)?

本文解釋在C51編程中,怎樣有效使用函數指針。特別地,討論如下幾個(gè)話(huà)題:

分配常量地址給一個(gè)指針;

定義函數指針;

C51中函數指針問(wèn)題;

使用OVERLAY指令確定調用樹(shù);

再入函數的指針;

固定地址的指針

你很容易的給函數指針?lè )峙湟粋€(gè)數字地址。有許多原因需要這樣做。例如,你需要復位目標。你可以設置函數指針為0000H去實(shí)現。

你可以使用標準C語(yǔ)言的類(lèi)型映射特點(diǎn),映射0X0000指針指向地址0的函數。例如,當你編譯如下C代碼….

((void (code *) (void))0x0000) ();

…編譯器產(chǎn)生如下如下代碼:

;FUNCTION main (BEGIN)

;SOURCELINE#3

0000120000LCALL00H

;SOURCELINE#4

000322RET

; FUNCTION main (END)

這正是我們期望的:LCALL0

把一個(gè)數字常量映射成一個(gè)函數指針是一件很復雜的事情。下面關(guān)于上面的函數調用的各部分的描述,將幫助你怎樣更好的使用它們。

在上面的函數調用中,(void ( *) (void))是數據類(lèi)型:一個(gè)不帶參數且返回void的函數指針。

0x0000是一個(gè)映射地址。經(jīng)過(guò)類(lèi)型映射,函數指針指向地址0x0000。注意我們把一個(gè)圓括號放在數據類(lèi)型和0x0000后面。如果我們僅僅想映射0x0000成為函數指針,這是不必要的。然而,因為我們將引用這個(gè)函數,這些圓括號是必要的。

映射一個(gè)數值常量成為指針和通過(guò)指針調用函數是不同的。為了實(shí)現這個(gè),我們必須指定一個(gè)變量表。這就是為什么在此行的后面有一個(gè)()。

注意上面表達式中的所有圓括號都是必須的。分組和優(yōu)先級是很重要的。

上面不帶參數的函數指針和帶參數的函數指針的唯一不同是數據類(lèi)型和變量列表。例如,下面的函數調用…..

((long (code *) (int int int ) 0x8000)(1,2,3);

聲明一個(gè)函數,地址在0x8000,接收3個(gè)int型參數,返回long型結果。

不帶參數的函數指針

指向函數的函數指針是可變的。函數的地址是一個(gè)可變的數值。例如,下面的函數指針的聲明….

void (*function_ptr) (void);

是一個(gè)調用function_ptr的指針。使用下面的代碼調用function_ptr函數。

(*function_ptr ) ();

因為函數沒(méi)有參數傳送,所以參數列表時(shí)空的。

當定義變量的時(shí)候,函數指針可以被分配地址:void (*function_ptr) (void) = another_fuction;或者在程序執行過(guò)程中被分配,function_ptr = another_fuction;

注意,必須分配一個(gè)地址給函數指針。如果沒(méi)有分配,函數指針將有一個(gè)0值(如果你運氣好),或者有一些你完全不知道的數值,依賴(lài)于你的數據存儲區的使用情況。當你間接的調用一個(gè)函數通過(guò)函數指針,如果函數指針沒(méi)有初始化,你的程序將是混亂的。

為了聲明一個(gè)帶返回值的函數指針,在聲明過(guò)程中你必須指定返回值的數據類(lèi)型。例如,下面的聲明改變了上面的函數指針的聲明,返回一個(gè)float 數據。

float(*function_ptr) (void) = another_fuction;

帶參數的函數指針

帶參數的函數指針與不帶參數的函數指針是相似的。例如:

void (*function_ptr) (int, long,char); 一個(gè)函數指針,帶一個(gè)int參數,帶一個(gè)long參數,帶一個(gè)char參數。使用下面的代碼調用函數。

(*function_ptr) (12, 34L,‘A’);

注意,函數指針僅僅可以指向小于等于3個(gè)參數的函數。這是因為,間接調用函數時(shí),參數必須保存在寄存器中。關(guān)于超過(guò)3個(gè)參數的函數指針的信息,在再入函數中介紹。

使用函數指針的附加說(shuō)明

如果你在C51中使用函數指針編程,有幾個(gè)附加的說(shuō)明你必須注意。

參數列表的限制

通過(guò)函數指針傳遞參數給函數必須把所有的參數存入寄存器。在大部分情況下,3個(gè)參數能夠自動(dòng)通過(guò)寄存器傳遞。在C51的用戶(hù)手冊中能找到傳遞參數進(jìn)入寄存器的運算法則。但是并不保證,任何的3個(gè)數據類(lèi)型可以傳遞。

因為C51在寄存器中傳遞3個(gè)參數,用于傳遞參數的存儲空間是不被分配的,除非函數指向一個(gè)要求更多參數的函數。如果在那樣的情況下,可以把參數混入一個(gè)結構體中,然后通過(guò)一個(gè)結構體指針傳遞參數。如果這樣不可接受,你可以使用再入函數(看下面)。

調用樹(shù)的保存

C51不把函數參數壓棧(除非使用再入函數)。函數參數和全局變量被存入寄存器或固定的存儲空間。這樣阻止函數的再入。例如,一個(gè)函數調用它自己,它將覆蓋它自己的參數或存儲空間。函數的再入問(wèn)題通過(guò)關(guān)鍵字“reentrant”來(lái)解決。函數指針的非再入函數的副作用,在執行中出現問(wèn)題。

為了保護盡量多的數據空間,連接器執行調用樹(shù)的性能分析,決定一些存儲空間被安全的覆蓋。例如,如果你的應用中包含main 函數,函數a,函數b,函數c,并且main函數調用a,b,c,但是a,b,c之間沒(méi)有互相調用。在你應用中的調用樹(shù)見(jiàn)出現如下:

MAIN

+→ A

+→ B

+→ C

這樣A,B,C的存儲空間可以被安全的覆蓋。

當調用樹(shù)不能正確的建立,函數指針將帶來(lái)問(wèn)題。因為連接器不能決定函數之間的引用。在這個(gè)問(wèn)題上,沒(méi)有自動(dòng)的解決方法。


上一頁(yè) 1 2 3 下一頁(yè)

關(guān)鍵詞: KeilC51函數指針再入函

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>