數(shù)據(jù)類型轉(zhuǎn)換_第1頁
數(shù)據(jù)類型轉(zhuǎn)換_第2頁
數(shù)據(jù)類型轉(zhuǎn)換_第3頁
數(shù)據(jù)類型轉(zhuǎn)換_第4頁
數(shù)據(jù)類型轉(zhuǎn)換_第5頁
已閱讀5頁,還剩8頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、數(shù)據(jù)類型轉(zhuǎn)換各類整數(shù)之間的轉(zhuǎn)換c語言中的數(shù)分8 位、 16 位和 32 位三種。屬于8 位數(shù)的有:帶符號字符 char ,無符號字符unsigned char 。屬于 16 位數(shù)的有:帶符號整數(shù) int ,無符號整數(shù)unsigned int(或簡寫為unsigned) , 近指針。屬于 32 位數(shù)的有:帶符號長整數(shù)long ,無符號長整數(shù) unsigned long,遠(yuǎn)指針。ibm pc 是 16 位機,基本運算是16 位的運算,所以,當(dāng)8 位數(shù)和 16 位數(shù)進(jìn)行比較或其它運算時,都是首先把8 位數(shù)轉(zhuǎn)換成16 位數(shù)。為了便于按 2 的補碼法則進(jìn)行運算,有符號8 位數(shù)在轉(zhuǎn)換為16 位時是在左邊添

2、加 8個符號位,無符號8 位數(shù)則是在左邊添加8 個 0。當(dāng)由 16 位轉(zhuǎn)換成8 位時,無論什么情況一律只是簡單地裁取低8 位,拋掉高8 位。沒有char 或 usigned char常數(shù)。字符常數(shù),像c,是轉(zhuǎn)換為int以后存儲的。當(dāng)字符轉(zhuǎn)換為其它 16 位數(shù) ( 如近指針 ) 時,是首先把字符轉(zhuǎn)換為int ,然后再進(jìn)行轉(zhuǎn)換。16 位數(shù)與 32 位數(shù)之間的轉(zhuǎn)換也遵守同樣的規(guī)則。注意, turbo c 中的輸入 / 輸出函數(shù)對其參數(shù)中的int和 unsigned int不加區(qū)分。例如,在printf函數(shù)中如果格式說明是%d 則對這兩種類型的參數(shù)一律按2 的補碼 ( 即按有符號數(shù) ) 進(jìn)行解釋,然后

3、以十進(jìn)制形式輸出。如果格式說明是%u 、%o 、%x、%x ,則對這兩種類型的參數(shù)一律按二進(jìn)制 ( 即按無符號數(shù)) 進(jìn)行解釋,然后以相應(yīng)形式輸出。在scanf 函數(shù)中,僅當(dāng)輸入的字符串中含有負(fù)號時,才按2 的補碼對輸入數(shù)進(jìn)行解釋。還應(yīng)注意,對于常數(shù),如果不加l,則 turbo c 一般按 int型處理。例如,語句printf(%081x,-1l) ,則會輸出ffffffff。如果省略1,則輸出常數(shù)的低字,即ffff。如果省略l,則仍會去找1 個雙字,這個雙字的就是int常數(shù) -1 ,高字內(nèi)容是不確定的,輸出效果將是在4 個亂七八糟的字符之后再跟ffff。在 turbo c 的頭文件value.

4、h中,相應(yīng)于3 個帶符號數(shù)的最大值,定義了 3 個符號常數(shù): #define maxshort 0x7fff #define maxint 0x7fff #define maxlong 0x7fffffffl 在 turbo c tools中,包括 3 對宏,分別把8 位拆成高4 位和低 4位,把 16 位拆成高8 位和低8 位,把32 位拆成高16 位和低16 位。 uthinyb(char value) utlonyb(char value) uthibyte(int value) utlobyte(int value) uthiword(long value) utloword(long

5、 valueu) 在 turbo c tools中,也包括相反的3 個宏,它們把兩個4 位組成一個 8位, 把兩個 8 位組成一個16 位, 把兩個 16 位組成一個32 位。 utnybbyt(hinyb, lonyb) utwdlong(hiword ,loword) utbyword(hibyte,lobyte) 實數(shù)與整數(shù)之間的轉(zhuǎn)換turbo c 中提供了兩種實數(shù):float和 double 。float 由 32 位組成,由高到低依次是:1個尾數(shù)符號位,8 個偏碼表示的指數(shù)位( 偏值 = 127) ,23 個尾數(shù)位。 double 由 64 位組成,由高到低依次是:1 個尾數(shù)符號位,

6、 11 個偏碼表示的指數(shù)位( 偏值 =1023) , 52 個尾數(shù)位。通過下列公式, 可以由尾數(shù)和指數(shù)計算出所代表的實數(shù)值: x=1. 尾數(shù) *2( 指數(shù) - 偏值 ) 下列幾種情況下,此公式不成立:指數(shù) =000.0且尾數(shù) =00.0,則 x=x= 0 指數(shù) =000.0且尾數(shù) !=00.0,則 x=0. 尾數(shù) *2(1- 偏值 ) 指數(shù) =11.1且尾數(shù) =00.0,則 x=指數(shù) =11.1且尾數(shù) !=00.0,則 x是一個無效數(shù)在 turbo c 的頭文件value.h中,相應(yīng)于實數(shù)所能達(dá)到的最大最小值,定義了如下幾個符號常數(shù): #define maxfloat 3.37e+38 #de

7、fine minfloat 8.43e-37 #define maxdouble 1.797693e+308 #define mindouble 2.225074e-308 實常數(shù)是按double 格式存放的,如果想按float 格式存放,則必須加后綴f,如: 1.23e+4f。當(dāng)把實數(shù)強制轉(zhuǎn)換為整數(shù)時,采取的是“向零靠攏的算法, 如: float值: 65432.6 -65432.6 轉(zhuǎn)換為 long ; 65432 -65432 轉(zhuǎn)換為 unsigned : 65432 104 如果不希望“向零靠攏”,而希望“四舍五入” ,則必須由程序員自己處理。一種辦法是先加上( 符號位 /2) ,然后

8、再進(jìn)行類型轉(zhuǎn)換。應(yīng)該注意的是:如果被轉(zhuǎn)換的實數(shù)值超過了目標(biāo)類型的表達(dá)范圍,則會產(chǎn)生錯誤。例如上面的float值-65432 , 6 轉(zhuǎn)換為 unsigned int值時,由于超過了目標(biāo)范圍,所產(chǎn)生的104 就是錯誤的。在65432。 6轉(zhuǎn)換為unsigned int的 65432 以后,可以用printf的%u格式輸出,如果用 %d 格式輸出,則會得到錯誤的結(jié)果。指針說明指針是包含另一變量的地址變量。它的一般說明形式,如int *fd, 其 fd 是一個指向整型變量的指針。比較復(fù)雜的指針說明,如*(*pfpi)(),可按如下幾個原則來理解:以標(biāo)識符為中心,一對方括號一般表示數(shù)組,一對圓括號一般

9、表示函數(shù)或強調(diào)某一優(yōu)先順序,方括號對和圓括號對為同一優(yōu)先級,方括號和圓括號比*號優(yōu)先級高。以下幾例解釋了這些原則的應(yīng)用。int *fip(),因圓括號優(yōu)先級高,幫fip 先與圓括號結(jié)合,說明fip是一個函數(shù),這個函數(shù)返回一個指向整數(shù)的指針。 int (*pfi)(),因兩對圓括號為同一優(yōu)先級,故從左到右,pfi 是一個指針,這個指針指向一個函數(shù),這個函數(shù)返回一個整數(shù)。 int *par,因方括號比*號優(yōu)先級高,故par 是一個數(shù)組,這個數(shù)組的每一個元素是指向整數(shù)的指針。int (*ptr),因方括號與圓括號為同一優(yōu)先級,故ptr 是一個指針,這個指針指向一個數(shù),這個數(shù)的每一個元素是一個整數(shù)。

10、int *(*pfpi)(),pfpi是一指針,這個指針指向一個函數(shù),這個函數(shù)返回一個提向整數(shù)的指針。指針與地址指針在使用之前必須初始化,給指針賦地址的方法一般有如下幾種:第一種很容易理解,通過取地址操作符取變量( 包括結(jié)構(gòu)變量 ) 的地址,如:char_c=a, *ptr_char; ptr_char=&c; 第二種是數(shù)組,因為不帶方括號的數(shù)組名等效于數(shù)組中第一個元素的地址, 即數(shù)組名也可看作是一個指針,所以有兩種辦法。如: char myname31, *ptr; ptr=myname; 或 ptr=&myname0; 第三種是動態(tài)分配的一塊內(nèi)存,這時往往帶有類型強制轉(zhuǎn)換,

11、但應(yīng)注意當(dāng)內(nèi)存不夠時,可能返回一個空(null)指針。如: struect complex double real, image; ; struct complex *ptr; ptr= struct complex *)malloc(sizeof(struct complex); 第四種是函數(shù),與數(shù)組名一樣,函數(shù)名也可以當(dāng)作一個地址,于是可以把函數(shù)名賦給一個指向函數(shù)的指針。函數(shù)名后面跟一個帶圓括號的參數(shù)表意味著計算函數(shù)的值,但僅有一個函數(shù)名則意味著指向函數(shù)的指針。如:double (*fx)(); double quad_poly(double); fx=quad_poly;指針運算常見的指

12、針運算有:指針加或減一個數(shù),指針增量,指針減量,指針比較等等。假設(shè)p是某數(shù)組第1 個元素的指針,則p+n 就是這個數(shù)組中第 n 個元素的地址,每個元素占多少存儲單元則由指針?biāo)笖?shù)組的類型來確定。但有兩點要注意:第一,上面這段話是c語言對指針運算的普遍規(guī)律,但具體到種c 編譯則有所不同,尤其是在80x86類型的機器上。turbo c 和microsoft c 6.0以前的版本把指針分為near、far 、huge,microsoft c 6.0又增加了based。在這幾種指針中,只有huge 嚴(yán)格遵守上面的指針運算規(guī)則,詳見下一節(jié)。第二,當(dāng)指針應(yīng)用于數(shù)組尤其是多維數(shù)組時,有時容易弄錯,下表說明了

13、數(shù)組法與指針法的區(qū)別。 1 維 2 維 3 維數(shù)組說明int x int y int z 指針說明int *xptr int *yptr int *zptr 數(shù)組法表示某元素地址&xi &yij &zijk 指針法表示某元素地址ptr+i *(yptr+i)+j *(*(zptr+i)+j)+k 數(shù)組法存取某元素xi yij zijk 指針法存取某元素*(ptr+i) *(*(yptr+i)+j)*(*(*(zptr+i)+j)+k)指針分類在 c 語言教科書上,指針就是指針,不存在分類的問題。我們經(jīng)常說“指向整數(shù)的指針”, “指向結(jié)構(gòu)的指針” , “指向函數(shù)的指針”等

14、等,只是說指針指向不同的目標(biāo),而不是說指針本身有什么區(qū)別。但是,在以80x86為基礎(chǔ)的微機上實現(xiàn)c 語言時,由于80x86的物理地址空間不是線性連續(xù)的而是分段的,為了提高效率,就必須對指針加以分類。各類指針的運算法則也不一樣。turbo c 2.0及以前的版本,microsoft c 6.0以前的版本,指針都是分類三類,近(near) ,遠(yuǎn)(far),巨 (huge) 。microsoft c 6.0版本中,出現(xiàn)了一種新的指外類型,這就是基(based) 指針。基指針綜合實現(xiàn)了近和遠(yuǎn)指針的優(yōu)點,它像近指針那么小那么快,又像遠(yuǎn)指針那樣可以尋址缺省數(shù)據(jù)段以外的目標(biāo)?;羔樳@個名字就反映了這類指針上

15、的實現(xiàn)方法:它是以程序員指定的某一地址為段基址。如果在c 源程序中使用了基指針,編譯程序一般先把所指定的段基址裝在es寄存器內(nèi)。在缺省的數(shù)據(jù)段內(nèi),程序員一般不會使用基指針。但若同時要使用多個數(shù)據(jù)段,基指則有其明顯的優(yōu)點。一、近 (near) 指針近指針是用于不超過64k 字節(jié)的單個數(shù)據(jù)段或碼段。對于數(shù)據(jù)指針,在微、小和中編譯模式下產(chǎn)生的數(shù)據(jù)指針是近指針,因為此時只有一個不超過64k 字節(jié)的數(shù)據(jù)段。對于碼( 即函數(shù)指針 ) 指針,在微、小和緊湊編譯模式下產(chǎn)生的碼指針是近指針,因為此時只一個不超過64k 字節(jié)的碼段。本章將只討論數(shù)據(jù)指針。近指針是16 位指針,它只含有地址的偏移量部分。為了形成32

16、 位的完整地址,編譯程序一般是反近指針與程序的數(shù)據(jù)段的段地址組合起來。因為在大部分情況下程序的數(shù)據(jù)段的段地址是裝在ds寄存器內(nèi),因此一般沒有必要裝載這個寄存器。此外,當(dāng)用匯編語言和c 語言混合編程時,匯編語言總是假設(shè)ds含有數(shù)據(jù)目標(biāo)的地址。雖然近指針占用空間最小,執(zhí)行速度最快,但它有一個嚴(yán)格的限制,即只能64k字節(jié)以內(nèi)的數(shù)據(jù),且只能存取程序的數(shù)據(jù)段內(nèi)的數(shù)據(jù)。如果在小模式下編譯一個程序,而這個程序企圖增量一個近指針使之超過第 65536 個字節(jié),則這個近的指針就會復(fù)位到0。下面就是這樣一個例子:char _near *p=(char _near *)0 xffff; p+; 由于近指針的這個嚴(yán)重

17、限制,所有在比較大或比較復(fù)雜的程序中,都無法使用。二、遠(yuǎn)(far)指針遠(yuǎn)指針不是讓編譯程序把程序數(shù)據(jù)段地址作為指針的段地址部分,而是把指針的段地址與指針的偏移量直接存放在指針內(nèi)。因此,遠(yuǎn)指針是由 4 個字節(jié)構(gòu)成。它可以指向內(nèi)存中的任一目標(biāo),可以用于任一編譯模式,盡管僅在緊湊、大和巨模式下遠(yuǎn)指針才是缺省的數(shù)據(jù)指針。因為遠(yuǎn)指針的段地址在指針內(nèi),熟悉80x86 匯編語言的人都知道,這意味著每次使用遠(yuǎn)指針時都需要重新裝載段寄存器,這顯然會降低速度。應(yīng)該注意:盡管遠(yuǎn)指針可以尋址內(nèi)存中的任一單元,但它所尋址的目標(biāo)也不能超過64k 字節(jié)。這是因為,遠(yuǎn)指針在增量或減量之類的算術(shù)運算時,也只是偏移量部分參與運算

18、,而段地址保持不變。因此,當(dāng)遠(yuǎn)指針增量或減量到超過64k 字節(jié)段邊界時就出錯。例如: char far *fp=(char far *)0 xb800ffff; fp+; 在指針加1 以后, fp 將指向 b800:0000,而不是所希望的c800:0000。此外,在進(jìn)行指針比較時,far指針還會引起另外一些問題。far 指針是由偏移量和段地址這樣一對16 位數(shù)來表示的,對于某一實際內(nèi)存地址, far指針不是唯一的,例如,far指針 1234:0005 、1230:0045 、1200:0345 、1000:2345 、0900:9345 等都是代表實際地址12345,這樣會引起許多麻煩。第一

19、,為了便于與“空”(null)指針 (0000: 0000)進(jìn)行比較,當(dāng)關(guān)系操作符“=”和“ != ”用于對far 指針進(jìn)行比較時,比較的是全部 32 位。否則,如果只比較16 位偏移量,那么任何偏移量為0 的指針都將是“空”(null)指針,這顯然不符合一般使用要求。但在進(jìn)行這32 位比較時,不是按20 位實際地址來比較,而是把段地址和偏移量當(dāng)作一個 32 位無符號長整數(shù)來比較。對于上面這個例子,假設(shè)這些指針分別叫作a、 b、c、d、e,盡管這5 個 far 指針指向的都是同一內(nèi)存單元,但下列表達(dá)式運算的結(jié)果卻都為“假”,從而得出錯誤的結(jié)論:if(a=b). if(b=c). if(c=d)

20、. if(d=e). if(a=c). if(a=d). 第二,當(dāng)用“” 、 “=” , “”和“ d). if(dc). if(cb). if(ba). if(ea).三、巨 (huge) 指針只有巨指針才是一般c 語言教科書上所說的指針,它像遠(yuǎn)指針也占 4 個字節(jié)。與遠(yuǎn)指針的顯著差別是:當(dāng)增量或減量超過64k 字節(jié)段邊界時,巨指針會自動修正段基址的值。因此,巨指針不但可以尋址內(nèi)存中的任一區(qū)域,而且所尋址的數(shù)據(jù)目標(biāo)可以超過64k 字節(jié)。例如:char huge *hp=(char huge *)0 xb800ffff; hp+; 在指針加1 后, hp 將指向 c800:0000。但是,巨指

21、針總是比較慢的,因為編譯必須生成一小段程序?qū)χ羔樳M(jìn)行32 位而不是16 位的加減運算。此外,由于huge 指針是規(guī)則化指針,每一個實際內(nèi)存地址只一個huge 指針,所有在指針比較時不會產(chǎn)生錯誤。四、基(based) 指針前面已經(jīng)說過,巨指針綜合了近指針和遠(yuǎn)指針的優(yōu)點。像近指針一樣,基指針只占兩個字節(jié),這兩個字節(jié)是地址的偏移量。像遠(yuǎn)指針一樣,基指針可以尋址內(nèi)存中的任一區(qū)域。近指針的段地址隱含地取自程序的數(shù)據(jù)段,遠(yuǎn)指針的段地址取自指針本身,基指針的段地址取法以及基指針的許多技術(shù)和應(yīng)用問題,請見第11 章。五、各類指針之間的轉(zhuǎn)換far指針可以強制轉(zhuǎn)換為near 指針,做法很簡單,拋掉段地址只保留偏移

22、量。near 指針也可以轉(zhuǎn)換為far 指針, turbo c 的做法是從相應(yīng)的段寄存器中取得段地址。far指針有時也需要轉(zhuǎn)換為huge 指針,以便對指針進(jìn)行比較或做其它操作。一種方法是通過下面這樣一個規(guī)則化函數(shù): void normalize(void far *p) *p=(void far *)(long)*p0 xffff000f)+ (long)*p0 x0000fff0)0) for(i=0;i result.stri=str1.stri; result.strlen=str1.strlen; if(str2.strlen0) j=stre1.strlen; for(i=0;i re

23、sult.stri+j=str2.stri; result.strlen+=str1.strlen; return result; 無返回值的函數(shù)無返回值的函數(shù)與pascal 等其它結(jié)構(gòu)化語言中的過程很相似,它們既不返回結(jié)果,又不修改參數(shù),而只是執(zhí)行某一特定的任務(wù)。例如,下面的清屏函數(shù)就是這樣一個函數(shù)。 void clrscr(void) printf(xlb2j); 既然不返回值,則調(diào)用的辦法也不一樣,不是把函數(shù)名放在某一表達(dá)式內(nèi)調(diào)用,而是把函數(shù)名連同其調(diào)用參數(shù)單獨人微言輕一個語句。修改參數(shù)的函數(shù)由于 c 語言是按傳值方式把參數(shù)傳遞給函數(shù)的,因此,被調(diào)用的函數(shù)不能直接改變調(diào)用函數(shù)中的變量。但

24、有時確實需要修改調(diào)用函數(shù)的參數(shù),尤其在返回值多于一個的函數(shù)中必須再借用參數(shù)來返回結(jié)果。在這些情況下,必須利用指針來從函數(shù)的參數(shù),典型的例子是交換兩個變量的值的函數(shù)。如下所示: void swap int(int *i,int *j) int temp; temp=*i; *i=*j; *j=temp; 遞歸函數(shù)c 語言是支持遞歸調(diào)用的。顯然,當(dāng)一個問題蘊含遞歸關(guān)系且結(jié)構(gòu)比較復(fù)雜時,采用遞歸調(diào)用技巧將使程序變得簡潔,并增加程序的可讀性。但遞歸調(diào)用技巧的使用是在犧牲存儲空間的基礎(chǔ)上得到的,因為它必須在某處維護(hù)一個要處理的值的棧。同時,遞歸也不能提高執(zhí)行速度,只是其代碼比較緊湊易讀。對于像樹和鏈表這

25、樣的遞歸定義的數(shù)據(jù)結(jié)構(gòu),遞歸函數(shù)尤為適用。下面是用遞歸計算階乘的例子。 double factorial(int n) if(n1) return factorial(n-1)*(double)n; else return 1.0l; 參數(shù)個數(shù)不定的函數(shù)c語言中的某些函數(shù),如vfprintf和 vprintf,允許在一些固定參數(shù)之后再帶一些不定數(shù)目的可變參數(shù)。不但如此,c 語言還允許用戶自定義的函數(shù)也這樣做。為了便于用戶編程,turbo c 中提供了以“va”開頭的4 個定義 va_list數(shù)據(jù)類型, va_stat ,va_arg 和 va_end 3 個宏 ( 函數(shù) ) 。這些定義都在頭文

26、件stdarg.h中。借助于這些宏可以一步一步地通過整修參數(shù)表,盡管被調(diào)用函數(shù)事先不知道有多少個參數(shù),也不知道這些參數(shù)的類型。為了編寫具有不定數(shù)目的可變參數(shù)函數(shù),應(yīng)遵守如下幾點:第 1,在 c源中包含stdarg.h文件。第 2,如果函數(shù)的返回值不是int型,則在調(diào)用函數(shù)中應(yīng)做如下形式的函數(shù)說明: (,.); 這個調(diào)用形式表明,參數(shù)表中至少必須有一個參數(shù)是固定的。第 3,函數(shù)應(yīng)按如下形式定義: (,.); 第 4,定義一個表指針,其類型應(yīng)是va_list,以表明它指向可變參數(shù)表。如下所示: va_list 第 5,調(diào)用va_start,初始化表指針:va_start(,) 這樣初始化后, 表指

27、針就指向了調(diào)用函數(shù)傳來的可變參數(shù)中的第1 個參數(shù)。第 6, 調(diào)用 va_arg , 取可變參數(shù): =va_arg(, ) 第1 次調(diào)用 va_arg 時,它返回可變參數(shù)表中的和第1 個參數(shù)。隨后每一次調(diào)用,它返回表中的下一個參數(shù)。每次調(diào)用之后自動修正表指針的值,使它指向隨后的一個參數(shù)。為了正確地停止讀可變參數(shù)表,應(yīng)該在調(diào)用函數(shù)可變參數(shù)表的最后放一個表結(jié)束符( 例如 -1 或 0) ,在被調(diào)用函數(shù)中再去檢查這個表結(jié)束符。while 循環(huán)很適合做這件事情,如下面的例子所示。第 7,調(diào)用 va_end,返回到調(diào)用函數(shù); va_end() 它幫助被調(diào)用函數(shù)正常返回到調(diào)用函數(shù)。應(yīng)在va_arg 讀完所有

28、參數(shù)之后,才調(diào)用va_end 返回,否則可能會引起意想不到的結(jié)果。下面這個例子利用一個具有可變參數(shù)表的函數(shù),從一個數(shù)字表中挑選值最大的那個數(shù)。 #include #include #define eol -1 main() int big; void vmax(int *,char *,.); vmax(&big,the largest of 55,67, 41 and 28 is,55,67,41,28,eol); printf(%dn,big); void vmax(int *large,char *message,.) int num; va_list num_ptr; va_s

29、tart(num_ptr,message); printf(%s,message); *large=-1; while(num=va_arg(num_ptr,int)!=eol) if(num*(large) *(large)=num; va_end(num_ptr); 函數(shù)指針及其應(yīng)用函數(shù)名后面跟一對圓括號( 興許括號內(nèi)還有參數(shù)) ,將導(dǎo)致去計算這個函數(shù)。僅僅一個函數(shù)名則意味著是一個指針,是指向這個函數(shù)的指針。函數(shù)指針有兩個特殊用途,不太熟練的程序員可能很少使用函數(shù)指針,但在某些場合下若借助于函數(shù)指針,則會使程序顯得非常精練。第 1 種用途是把函數(shù)名賦給一個指針,然后用這個指針去間接引用函數(shù)

30、。請看下面這個例子: #include main() double x; const double delta=1.0; const double first=0.0; const double last=10.0; double (*fx)(); double quad_poly(double); fx=quad_poly; x=first; while(x=last) printf(f(%1f)=%1fn,x,fx(x); x+=delta; double quad_poly(double x) double a=1.0,b=-3.0,c=5.0; return (x*a)*x+b)*x+

31、c; 在這個例子里,語句double(*fx)() 說明 fx 是一個函數(shù)指針,該函數(shù)返回一個double 型數(shù)。然后把函數(shù)名quad_poly 賦給這個指針。通過 fx(x) 引用這個函數(shù),取得函數(shù)的返回值。有時候,程序中要用到多個函數(shù),這些函數(shù)有相同的參數(shù)要求和相同的返回值類型。但這些函數(shù)不是同時都要用到,而是根據(jù)不同的情況每次僅調(diào)用其中的一個。比較笨拙的辦法就是用switch語句去實現(xiàn),雖然也還清楚,但程序顯得冗長。用函數(shù)指針則顯得精練多了,如下面的例子所示: #include #include #include #define max 3 main() double x; const

32、double delta=1.0; const double first=0.0; const double last=1.0; double (*fxmax)(); int i; char ch; double quad_poly(double); fx0=quad_poly; fx1=sqrt; fx2=log; for(i=0;i x=first; while(x%1f,first,last); printf(is %1fn,find_largest(first,last,delta,fx); double quad_poly(double x) double a=1.0,b=-3.0,

33、c=5.0; return (x*a)*x+b)*x+c; double find_largest(double a,double b,double step,double (*fx)() double x=a,big=(*fx)(a); while(x=b) if(big(*fx)() big=(*fx)(x); x+=step; return big; 在這個例子里,函數(shù)quad_poly 計算 (a*x3+b*x+c)的值,參數(shù)x 和返回值教師double 型數(shù)。函數(shù)find_largest根據(jù)某一計算法則求出在某一范圍內(nèi) ( 某一步長 ) 的最大值。不但范圍和步長是由調(diào)用參數(shù)指定,計算

34、法則也是由調(diào)用參數(shù)指定,所有的參數(shù)返回值都是double 型數(shù)。主函數(shù) main 調(diào)用 find_largest求最大值,通過函數(shù)指針把函數(shù)quad_poly 人微言輕參數(shù)傳給find_largest。段與偏移量8086 和 80286 的寄存器都是8 位或 16 位的,而8086 以及工作于實地址方式下的80286/80386 的地址空間卻是20 位的。這樣在尋找下一條將執(zhí)行的指令時以及當(dāng)用寄存器間接尋址內(nèi)存中某一數(shù)據(jù)時,16 位的指針寄存器和地址寄存器卻不足以存下20 位地址。為了解決這個問題,便把 20 位地址分為兩部分,分別稱為段地址和偏移量。段地址可以是任一 16 字節(jié)邊界處,即段地

35、址的末4 位一定是0,不需要保存,只把高16 位存入段寄存器中。偏移量也是16 位的,一方面便于寄存器間接尋址,但另一方面也限制了每段不能超過64k 字節(jié)。考慮到程序和數(shù)據(jù)的尋址一般都是連續(xù)的,故這種設(shè)計還是合理的。在 80x86 微機中,總是有4 個 16 位段寄存器:cs ,ds ,ss ,es。在turbo c 編譯產(chǎn)生的目標(biāo)碼中,一般只用到了其中的3 個寄存器, cs用來存放碼的段地址,ds用來存放全局變量和靜態(tài)變量所在段的段地址,ss用來存放局部變量,參數(shù)( 以及其它屬于某一個函數(shù)的信息) 所在段的段地址。在microsoft c 6.0中, es用來存放基指針的段地址。如果需要,在

36、turbo c 中,程序員可以通過偽變量_ds 、_cs 、_ss、_es 取得這些段寄存器的值。如果程序的碼、數(shù)據(jù)和堆棧分別都不超過連續(xù)64k 字節(jié),則在程序的整修執(zhí)行過程中,cs 、ds和 ss寄存器的值可以不變,僅僅通過對單字偏移量的操作就可以尋址到所有的碼和變量,這樣速度比較快。如果碼或數(shù)據(jù)不能在邊續(xù)64k 字節(jié)內(nèi)放下,則必須用雙字的段:偏移量來尋址,但速度也就變慢。在所有程序中,堆棧的操作都較頻繁,所以都禁止使用雙字的尋址方法,并限制堆棧不能超過64k 字節(jié),即不超過一段,盡管有時各個程序模塊使用自己獨立的堆棧。有時,我們知道了某一個存儲單元的段地址,也知道它的偏移量,也知道它的偏移

37、量,但這個段地址和偏移量并沒有構(gòu)成一個遠(yuǎn)指針。turbo c 中提供了如下4 個宏,使得可以從這個內(nèi)存單元中讀( 或往這個內(nèi)存單元中寫)1 個字節(jié) ( 或 1 個整數(shù) ) 。char peekb(unsigned segment,unsigned offset) int peek(unsigned segment,unsigned offset) void pokeb(unsigned segment,unsigned offset,char value) void poke(unsigned segment,unsigned offset,int value) 下面是從rom 的地址 fff

38、f:000e中讀 1個字節(jié)的例子,這個字節(jié)實際上就是微機類型的標(biāo)志字節(jié)。/* #include*/ #include void main() printf(pc model=hex%x,( char ) peekb(0 xffff,0 x000e); 這 4 個宏以及下面將介紹的3 個宏的定義都在頭文件dos.h 中,但在頭文件general.h中包含有 #include這樣一行,所以在上面這個例子中只寫了#include。因為下面經(jīng)常要用到general.h,故單獨把它列出來。/* general.h */ #include #include #include #include #inclu

39、de #include #define boolean int #define true 1 #define false 0 #define blank #define cr 13 #define beep putchar(a) #define newline putchar(n) #define emptystr #define farnull (void far *)null #define inta00 0 x20 #define eoi 0 x20 #define strempty(s) (*(s)=0) boolean strequalsf(char *s,char *t,char *ps,char *pt); boolean strequalsb(char *s,char *t,char *pm,char *pn); #define strchrf strchr char *strchrb(char *s,char *p,char c); #define strpbrkf strpbrk char *strstrf(char *s,char *t); char *strstrb(char *s,char *t); char *stralloc(char ch,unsigned n); char *strsubst(char *s,char *a,

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論