Delphi指针大全
生活随笔
收集整理的這篇文章主要介紹了
Delphi指针大全
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Delphi指針理解 看一個指針用法的例子:??
?? 1????????? var??
?? 2????????????? X,??? Y:??? Integer;??????? //??? X??? and??? Y??? 整數(shù)類型??
?? 3????????????? P:??? ^Integer;??????????? //??? P??? 指向整數(shù)類型的指針??
?? 4????????? begin??
?? 5????????????? X??? :=17; //??? 給??? X??? 賦值??
?? 6????????????? P??? :=??? @X;??????????????????? //??? 把??? x的地址賦給p??
?? 7????????????? Y??? :=??? P^;??????????????????? //??? 取出p所指向的數(shù)值賦給y??
?? 8????????? end;??
???
?? 第二行定義了兩個變量X,y.??? 第三行聲明了p是指向整數(shù)類型的指針;意味著p能夠指向x或者y的地址.第五行賦給x值,第六行把x的地址賦給p.最??
???
?? 后通過p指向的變量賦值給y.此時,x和y有相同的值.??
???
?? 操作符@用來取出變量的地址,也可以取出過程和函數(shù)的地址.??
???
?? 而符號^有兩個目標(biāo),??
?? 當(dāng)它出現(xiàn)在類型定義的前面時如 ^typename 表示指向這種類型的指針;??
?? 當(dāng)它出現(xiàn)在指針變量后邊時??? 如 point^ 返回指針指向的變量的值;??
???
?? 理解指針比較容易理解面向?qū)ο蟮膒ascal語言,因為指針經(jīng)常在幕后操作.任何要求動態(tài)分配大的內(nèi)存空間的類型可以用指針類型.例如??
???
?? ,long-string變量,實際在使用指針進(jìn)行操作.另外一些高級的編程技術(shù)需要使用指針類型.??
?? 有時指針是適應(yīng)object??? pascal嚴(yán)格的類型限制的唯一方法.同過一個通用的指針類型,通過類型轉(zhuǎn)換成不同的指針類型,如下面的例子:??
?? type??
???
?????? PInteger??? =??? ^Integer;??
?? var??
?????? R:??? Single;??
?????? I:??? Integer;??
?????? P:??? Pointer; //通用的指針??
?????? PI:??? PInteger;??
?? begin??
?????? P??? :=??? @R; //取出R的內(nèi)存地址??
?????? PI??? :=??? PInteger(P); //把通用類型轉(zhuǎn)換成指向整數(shù)類型的指針??
?????? I??? :=??? PI^;??
?? end;??
???
?? 當(dāng)然了,實數(shù)和整數(shù)的存儲格式不同.這種賦值是把原始的二進(jìn)制數(shù)據(jù)從R拷貝到I,而不進(jìn)行轉(zhuǎn)換.??
???
?? 保留字nil是一個特殊的常量可以賦給任何指針類型,當(dāng)nil賦給一個指針時,指針什么也不指向,是一個空指針.??
???
?? @操作符返回變量的內(nèi)存中的存儲地址,或者是過程\函數(shù)\方法;??
???
?? 1.如果變量,@X返回的是x的地址。如果編譯選項{$T-}沒有打開,著返回的事一個通用的指針,如果編譯選項打開了,著返回的是x的類型對應(yīng)的指??
???
?? 針.??
???
?? 2.如果是例程(過程\函數(shù)),@F返回的是F的入口點,@F的類型是一個指針。??
???
?? 3.當(dāng)@用在類的方法中時,則方法的名稱必須有類名,例如@TMyclass.Dosomething??
?? 指針指向TMyclass的dosomething方法。??
???
???
?? 當(dāng)一個過程變量在賦值語句的左邊時,編譯器期望一個過程值在賦值語句的右邊。這種賦值使得左邊的變量可以指向右邊定義的過程或者函數(shù)??
???
?? 入口點。換句話說,可以通過該變量來引用聲明的過程或者函數(shù),可以直接使用參數(shù)的引用。??
???
?? var??
???
?????? F:??? function(X:??? Integer):??? Integer;??
?????? I:??? Integer;??
?? function??? SomeFunction(X:??? Integer):??? Integer;??
???? ...??
?? F??? :=??? SomeFunction;????? //??? 給f賦值??
?? I??? :=??? F(4);????????????????????? //??? 調(diào)用所指向的函數(shù)??
???
?? 在賦值語句中,左邊變量的類型決定了右邊的過程或者方法指針解釋。??
???
?? var??
???
?????? F,??? G:??? function:??? Integer;??
?????? I:??? Integer;??
?? function??? SomeFunction:??? Integer;??
???? ...??
?? F??? :=??? SomeFunction;????? //??? 給f賦值??
?? G??? :=??? F;??????????????????????????? //??? 把F的值拷貝給G??
?? I??? :=??? G;??????????????????????????? //??? 調(diào)用函數(shù)??
???
?? 第一句獲得函數(shù)的入口,第二句將指針復(fù)制,第三句獲得函數(shù)的返回值。??
???
?? 有時候還可以這樣使用??
?? if??? F??? =??? MyFunction??? then??? ...;??
?? 在這里,F的出現(xiàn)導(dǎo)致一個函數(shù)調(diào)用;編譯器調(diào)用F指向的函數(shù),然后調(diào)用Myfunction,比較結(jié)果。這個規(guī)則是無論何時一個過程變量(??
???
?? procedural??? variable)出現(xiàn)在一個表達(dá)式中,它表示調(diào)用所指向的函數(shù)或者過程。有時F指向一個過程(沒有返回值),或者f指向一個需要參??
???
?? 數(shù)的函數(shù),則前面的語句會產(chǎn)生一個編譯錯誤。要比較F和Myfunction需要用??
?? if??? @F??? =??? @MyFunction??? then??? ...;??
?? @F把F轉(zhuǎn)換成一個包含地址的無類型的指針變量,@myfunction返回myfunction的地址。??
?? 獲得一個過程變量的內(nèi)存地址使用@@。例如,@@F返回F的地址。??
???
?? @操作符通常把一個無類型的指針值賦給一個過程變量,例如:??
?? var??? StrComp:??? function(Str1,??? Str2:??? PChar):??? Integer;??
???? ...??
?? @StrComp??? :=??? GetProcAddress(KernelHandle,??? 'lstrcmpi');??
?? 調(diào)用GetProcAddres函數(shù),用strcomp指向這個值??
?? 任何過程變量可以賦成nil,表示指證什么也不指向。但是試圖調(diào)用一個nil值的過程變量導(dǎo)致一個錯誤,為了測試一個過程變量是否可以賦值??
???
?? ,用標(biāo)準(zhǔn)的賦值函數(shù)Assigned??
?? if??? Assigned(OnClick)??? then??? OnClick(X);?? ========================================================================= 大家都認(rèn)為,C語言之所以強(qiáng)大,以及其自由性,很大部分體現(xiàn)在其靈活的指針運用上。因此,說指針是C語言的靈魂,一點都不為過。同時,這種說法也讓很多人 產(chǎn)生誤解,似乎只有C語言的指針才能算指針。Basic不支持指針,在此不論。其實,Pascal語言本身也是支持指針的。從最初的Pascal發(fā)展至今 的Object Pascal,可以說在指針運用上,絲毫不會遜色于C語言的指針。?
以下內(nèi)容分為八個部分,分別是?
一、類型指針的定義?
二、無類型指針的定義?
三、指針的解除引用?
四、取地址(指針賦值)?
五、指針運算?
六、動態(tài)內(nèi)存分配?
七、字符數(shù)組的運算?
八、函數(shù)指針?
一、類型指針的定義。對于指向特定類型的指針,在C中是這樣定義的:?
int *ptr;?
char *ptr;?
與之等價的Object Pascal是如何定義的呢??
var?
ptr : ^Integer;?
ptr : ^char;?
其實也就是符號的差別而已。?
二、無類型指針的定義。C中有void *類型,也就是可以指向任何類型數(shù)據(jù)的指針。Object Pascal為其定義了一個專門的類型:Pointer。于是,?
ptr : Pointer;?
就與C中的?
void *ptr;?
等價了。?
三、指針的解除引用。要解除指針引用(即取出指針?biāo)竻^(qū)域的值),C 的語法是 (*ptr),Object Pascal則是 ptr^。?
四、取地址(指針賦值)。取某對象的地址并將其賦值給指針變量,C 的語法是?
ptr = &Object;?
Object Pascal 則是?
ptr := @Object;?
也只是符號的差別而已。?
五、指針運算。在C中,可以對指針進(jìn)行移動的運算,如:?
char a[20];???
char *ptr=a;???
ptr++;?
ptr+=2;?
當(dāng)執(zhí)行ptr++;時,編譯器會產(chǎn)生讓ptr前進(jìn)sizeof(char)步長的代碼,之后,ptr將指向a[1]。ptr+=2;這句使得ptr前進(jìn)兩 個sizeof(char)大小的步長。同樣,我們來看一下Object Pascal中如何實現(xiàn):?
var?
?? a : array [1..20] of Char;?
?? ptr : PChar; //PChar 可以看作 ^Char?
begin?
?? ptr := @a;?
?? Inc(ptr); // 這句等價于 C 的 ptr++;?
?? Inc(ptr, 2); //這句等價于 C 的 ptr+=2;?
end;?
六、動態(tài)內(nèi)存分配。C中,使用malloc()庫函數(shù)分配內(nèi)存,free()函數(shù)釋放內(nèi)存。如這樣的代碼:?
int *ptr, *ptr2;?
int i;?
ptr = (int*) malloc(sizeof(int) * 20);?
ptr2 = ptr;?
for (i=0; i<20; i++){?
?? *ptr = i;?
?? ptr++;?
}?
free(ptr2);?
Object Pascal中,動態(tài)分配內(nèi)存的函數(shù)是GetMem(),與之對應(yīng)的釋放函數(shù)為FreeMem()(傳統(tǒng)Pascal中獲取內(nèi)存的函數(shù)是New()和 Dispose(),但New()只能獲得對象的單個實體的內(nèi)存大小,無法取得連續(xù)的存放多個對象的內(nèi)存塊)。因此,與上面那段C的代碼等價的 Object Pascal的代碼為:?
var ptr, ptr2 : ^integer;?
?? i : integer;?
begin?
?? GetMem(ptr, sizeof(integer) * 20);?
???? //這句等價于C的 ptr = (int*) malloc(sizeof(int) * 20);?
?? ptr2 := ptr; //保留原始指針位置?
?? for i := 0 to 19 do?
?? begin?
???? ptr^ := i;?
???? Inc(ptr);?
?? end;?
?? FreeMem(ptr2);?
end;?
對于以上這個例子(無論是C版本的,還是Object Pascal版本的),都要注意一個問題,就是分配內(nèi)存的單位是字節(jié)(BYTE),因此在使用GetMem時,其第二個參數(shù)如果想當(dāng)然的寫成 20,那么就會出問題了(內(nèi)存訪問越界)。因為GetMem(ptr, 20);實際只分配了20個字節(jié)的內(nèi)存空間,而一個整形的大小是四個字節(jié),那么訪問第五個之后的所有元素都是非法的了(對于malloc()的參數(shù)同 樣)。
?? 1????????? var??
?? 2????????????? X,??? Y:??? Integer;??????? //??? X??? and??? Y??? 整數(shù)類型??
?? 3????????????? P:??? ^Integer;??????????? //??? P??? 指向整數(shù)類型的指針??
?? 4????????? begin??
?? 5????????????? X??? :=17; //??? 給??? X??? 賦值??
?? 6????????????? P??? :=??? @X;??????????????????? //??? 把??? x的地址賦給p??
?? 7????????????? Y??? :=??? P^;??????????????????? //??? 取出p所指向的數(shù)值賦給y??
?? 8????????? end;??
???
?? 第二行定義了兩個變量X,y.??? 第三行聲明了p是指向整數(shù)類型的指針;意味著p能夠指向x或者y的地址.第五行賦給x值,第六行把x的地址賦給p.最??
???
?? 后通過p指向的變量賦值給y.此時,x和y有相同的值.??
???
?? 操作符@用來取出變量的地址,也可以取出過程和函數(shù)的地址.??
???
?? 而符號^有兩個目標(biāo),??
?? 當(dāng)它出現(xiàn)在類型定義的前面時如 ^typename 表示指向這種類型的指針;??
?? 當(dāng)它出現(xiàn)在指針變量后邊時??? 如 point^ 返回指針指向的變量的值;??
???
?? 理解指針比較容易理解面向?qū)ο蟮膒ascal語言,因為指針經(jīng)常在幕后操作.任何要求動態(tài)分配大的內(nèi)存空間的類型可以用指針類型.例如??
???
?? ,long-string變量,實際在使用指針進(jìn)行操作.另外一些高級的編程技術(shù)需要使用指針類型.??
?? 有時指針是適應(yīng)object??? pascal嚴(yán)格的類型限制的唯一方法.同過一個通用的指針類型,通過類型轉(zhuǎn)換成不同的指針類型,如下面的例子:??
?? type??
???
?????? PInteger??? =??? ^Integer;??
?? var??
?????? R:??? Single;??
?????? I:??? Integer;??
?????? P:??? Pointer; //通用的指針??
?????? PI:??? PInteger;??
?? begin??
?????? P??? :=??? @R; //取出R的內(nèi)存地址??
?????? PI??? :=??? PInteger(P); //把通用類型轉(zhuǎn)換成指向整數(shù)類型的指針??
?????? I??? :=??? PI^;??
?? end;??
???
?? 當(dāng)然了,實數(shù)和整數(shù)的存儲格式不同.這種賦值是把原始的二進(jìn)制數(shù)據(jù)從R拷貝到I,而不進(jìn)行轉(zhuǎn)換.??
???
?? 保留字nil是一個特殊的常量可以賦給任何指針類型,當(dāng)nil賦給一個指針時,指針什么也不指向,是一個空指針.??
???
?? @操作符返回變量的內(nèi)存中的存儲地址,或者是過程\函數(shù)\方法;??
???
?? 1.如果變量,@X返回的是x的地址。如果編譯選項{$T-}沒有打開,著返回的事一個通用的指針,如果編譯選項打開了,著返回的是x的類型對應(yīng)的指??
???
?? 針.??
???
?? 2.如果是例程(過程\函數(shù)),@F返回的是F的入口點,@F的類型是一個指針。??
???
?? 3.當(dāng)@用在類的方法中時,則方法的名稱必須有類名,例如@TMyclass.Dosomething??
?? 指針指向TMyclass的dosomething方法。??
???
???
?? 當(dāng)一個過程變量在賦值語句的左邊時,編譯器期望一個過程值在賦值語句的右邊。這種賦值使得左邊的變量可以指向右邊定義的過程或者函數(shù)??
???
?? 入口點。換句話說,可以通過該變量來引用聲明的過程或者函數(shù),可以直接使用參數(shù)的引用。??
???
?? var??
???
?????? F:??? function(X:??? Integer):??? Integer;??
?????? I:??? Integer;??
?? function??? SomeFunction(X:??? Integer):??? Integer;??
???? ...??
?? F??? :=??? SomeFunction;????? //??? 給f賦值??
?? I??? :=??? F(4);????????????????????? //??? 調(diào)用所指向的函數(shù)??
???
?? 在賦值語句中,左邊變量的類型決定了右邊的過程或者方法指針解釋。??
???
?? var??
???
?????? F,??? G:??? function:??? Integer;??
?????? I:??? Integer;??
?? function??? SomeFunction:??? Integer;??
???? ...??
?? F??? :=??? SomeFunction;????? //??? 給f賦值??
?? G??? :=??? F;??????????????????????????? //??? 把F的值拷貝給G??
?? I??? :=??? G;??????????????????????????? //??? 調(diào)用函數(shù)??
???
?? 第一句獲得函數(shù)的入口,第二句將指針復(fù)制,第三句獲得函數(shù)的返回值。??
???
?? 有時候還可以這樣使用??
?? if??? F??? =??? MyFunction??? then??? ...;??
?? 在這里,F的出現(xiàn)導(dǎo)致一個函數(shù)調(diào)用;編譯器調(diào)用F指向的函數(shù),然后調(diào)用Myfunction,比較結(jié)果。這個規(guī)則是無論何時一個過程變量(??
???
?? procedural??? variable)出現(xiàn)在一個表達(dá)式中,它表示調(diào)用所指向的函數(shù)或者過程。有時F指向一個過程(沒有返回值),或者f指向一個需要參??
???
?? 數(shù)的函數(shù),則前面的語句會產(chǎn)生一個編譯錯誤。要比較F和Myfunction需要用??
?? if??? @F??? =??? @MyFunction??? then??? ...;??
?? @F把F轉(zhuǎn)換成一個包含地址的無類型的指針變量,@myfunction返回myfunction的地址。??
?? 獲得一個過程變量的內(nèi)存地址使用@@。例如,@@F返回F的地址。??
???
?? @操作符通常把一個無類型的指針值賦給一個過程變量,例如:??
?? var??? StrComp:??? function(Str1,??? Str2:??? PChar):??? Integer;??
???? ...??
?? @StrComp??? :=??? GetProcAddress(KernelHandle,??? 'lstrcmpi');??
?? 調(diào)用GetProcAddres函數(shù),用strcomp指向這個值??
?? 任何過程變量可以賦成nil,表示指證什么也不指向。但是試圖調(diào)用一個nil值的過程變量導(dǎo)致一個錯誤,為了測試一個過程變量是否可以賦值??
???
?? ,用標(biāo)準(zhǔn)的賦值函數(shù)Assigned??
?? if??? Assigned(OnClick)??? then??? OnClick(X);?? ========================================================================= 大家都認(rèn)為,C語言之所以強(qiáng)大,以及其自由性,很大部分體現(xiàn)在其靈活的指針運用上。因此,說指針是C語言的靈魂,一點都不為過。同時,這種說法也讓很多人 產(chǎn)生誤解,似乎只有C語言的指針才能算指針。Basic不支持指針,在此不論。其實,Pascal語言本身也是支持指針的。從最初的Pascal發(fā)展至今 的Object Pascal,可以說在指針運用上,絲毫不會遜色于C語言的指針。?
以下內(nèi)容分為八個部分,分別是?
一、類型指針的定義?
二、無類型指針的定義?
三、指針的解除引用?
四、取地址(指針賦值)?
五、指針運算?
六、動態(tài)內(nèi)存分配?
七、字符數(shù)組的運算?
八、函數(shù)指針?
一、類型指針的定義。對于指向特定類型的指針,在C中是這樣定義的:?
int *ptr;?
char *ptr;?
與之等價的Object Pascal是如何定義的呢??
var?
ptr : ^Integer;?
ptr : ^char;?
其實也就是符號的差別而已。?
二、無類型指針的定義。C中有void *類型,也就是可以指向任何類型數(shù)據(jù)的指針。Object Pascal為其定義了一個專門的類型:Pointer。于是,?
ptr : Pointer;?
就與C中的?
void *ptr;?
等價了。?
三、指針的解除引用。要解除指針引用(即取出指針?biāo)竻^(qū)域的值),C 的語法是 (*ptr),Object Pascal則是 ptr^。?
四、取地址(指針賦值)。取某對象的地址并將其賦值給指針變量,C 的語法是?
ptr = &Object;?
Object Pascal 則是?
ptr := @Object;?
也只是符號的差別而已。?
五、指針運算。在C中,可以對指針進(jìn)行移動的運算,如:?
char a[20];???
char *ptr=a;???
ptr++;?
ptr+=2;?
當(dāng)執(zhí)行ptr++;時,編譯器會產(chǎn)生讓ptr前進(jìn)sizeof(char)步長的代碼,之后,ptr將指向a[1]。ptr+=2;這句使得ptr前進(jìn)兩 個sizeof(char)大小的步長。同樣,我們來看一下Object Pascal中如何實現(xiàn):?
var?
?? a : array [1..20] of Char;?
?? ptr : PChar; //PChar 可以看作 ^Char?
begin?
?? ptr := @a;?
?? Inc(ptr); // 這句等價于 C 的 ptr++;?
?? Inc(ptr, 2); //這句等價于 C 的 ptr+=2;?
end;?
六、動態(tài)內(nèi)存分配。C中,使用malloc()庫函數(shù)分配內(nèi)存,free()函數(shù)釋放內(nèi)存。如這樣的代碼:?
int *ptr, *ptr2;?
int i;?
ptr = (int*) malloc(sizeof(int) * 20);?
ptr2 = ptr;?
for (i=0; i<20; i++){?
?? *ptr = i;?
?? ptr++;?
}?
free(ptr2);?
Object Pascal中,動態(tài)分配內(nèi)存的函數(shù)是GetMem(),與之對應(yīng)的釋放函數(shù)為FreeMem()(傳統(tǒng)Pascal中獲取內(nèi)存的函數(shù)是New()和 Dispose(),但New()只能獲得對象的單個實體的內(nèi)存大小,無法取得連續(xù)的存放多個對象的內(nèi)存塊)。因此,與上面那段C的代碼等價的 Object Pascal的代碼為:?
var ptr, ptr2 : ^integer;?
?? i : integer;?
begin?
?? GetMem(ptr, sizeof(integer) * 20);?
???? //這句等價于C的 ptr = (int*) malloc(sizeof(int) * 20);?
?? ptr2 := ptr; //保留原始指針位置?
?? for i := 0 to 19 do?
?? begin?
???? ptr^ := i;?
???? Inc(ptr);?
?? end;?
?? FreeMem(ptr2);?
end;?
對于以上這個例子(無論是C版本的,還是Object Pascal版本的),都要注意一個問題,就是分配內(nèi)存的單位是字節(jié)(BYTE),因此在使用GetMem時,其第二個參數(shù)如果想當(dāng)然的寫成 20,那么就會出問題了(內(nèi)存訪問越界)。因為GetMem(ptr, 20);實際只分配了20個字節(jié)的內(nèi)存空間,而一個整形的大小是四個字節(jié),那么訪問第五個之后的所有元素都是非法的了(對于malloc()的參數(shù)同 樣)。
總結(jié)
以上是生活随笔為你收集整理的Delphi指针大全的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 飞鸽传书 获得磁盘的C#描述信息
- 下一篇: 企业到底需要什么样的飞鸽传书