色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

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

          Keil C51 中的函數(shù)指針和再入函數(shù)

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

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

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

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

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

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

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

          分配常量地址給一個指針;

          定義函數(shù)指針;

          C51中函數(shù)指針問題;

          使用OVERLAY指令確定調(diào)用樹;

          再入函數(shù)的指針;

          固定地址的指針

          你很容易的給函數(shù)指針分配一個數(shù)字地址。有許多原因需要這樣做。例如,你需要復位目標。你可以設(shè)置函數(shù)指針為0000H去實現(xiàn)。

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

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

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

          ;FUNCTION main (BEGIN)

          ;SOURCELINE#3

          0000120000LCALL00H

          ;SOURCELINE#4

          000322RET

          ; FUNCTION main (END)

          這正是我們期望的:LCALL0

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

          在上面的函數(shù)調(diào)用中,(void ( *) (void))是數(shù)據(jù)類型:一個不帶參數(shù)且返回void的函數(shù)指針。

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

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

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

          上面不帶參數(shù)的函數(shù)指針和帶參數(shù)的函數(shù)指針的唯一不同是數(shù)據(jù)類型和變量列表。例如,下面的函數(shù)調(diào)用…..

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

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

          不帶參數(shù)的函數(shù)指針

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

          void (*function_ptr) (void);

          是一個調(diào)用function_ptr的指針。使用下面的代碼調(diào)用function_ptr函數(shù)。

          (*function_ptr ) ();

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

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

          注意,必須分配一個地址給函數(shù)指針。如果沒有分配,函數(shù)指針將有一個0值(如果你運氣好),或者有一些你完全不知道的數(shù)值,依賴于你的數(shù)據(jù)存儲區(qū)的使用情況。當你間接的調(diào)用一個函數(shù)通過函數(shù)指針,如果函數(shù)指針沒有初始化,你的程序?qū)⑹腔靵y的。

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

          float(*function_ptr) (void) = another_fuction;

          帶參數(shù)的函數(shù)指針

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

          void (*function_ptr) (int, long,char); 一個函數(shù)指針,帶一個int參數(shù),帶一個long參數(shù),帶一個char參數(shù)。使用下面的代碼調(diào)用函數(shù)。

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

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

          使用函數(shù)指針的附加說明

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

          參數(shù)列表的限制

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

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

          調(diào)用樹的保存

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

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

          MAIN

          +→ A

          +→ B

          +→ C

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

          當調(diào)用樹不能正確的建立,函數(shù)指針將帶來問題。因為連接器不能決定函數(shù)之間的引用。在這個問題上,沒有自動的解決方法。


          上一頁 1 2 3 下一頁

          評論


          技術(shù)專區(qū)

          關(guān)閉