delphi指针
delphi中由于vcl的存在,于是指針很少用到。昨天和“賤男”(一個做sp的朋友)在討論一個多線程的問題,最后考慮是不是指針傳遞的錯誤。 要求是這樣的:sql的數據庫,程序中的主線程以sql查詢獲取二十條記錄,然后傳遞給子線程,主線程掛起。while ....not語句,一條條賦給子線程,每子線程存一條記錄,以指針傳遞的(pchar).應用華為的api(vc編寫)其中LPCSTR用delphi 中pchar代替,但是最后子線程得到的數據是亂七八遭的東西。不從數據庫讀取數據,讀字符串和變量都是正確的,實在不解?是不是指針傳遞數據時候出錯?
順便放出pascal的指針: 淺談Object Pascal的指針
大家都認為,C語言之所以強大,以及其自由性,很大部分體現在其靈活的指針運用上。因此,說指針是C語言的靈魂,一點都不為過。同時,這種說法也讓很多人 產生誤解,似乎只有C語言的指針才能算指針。Basic不支持指針,在此不論。其實,Pascal語言本身也是支持指針的。從最初的Pascal發展至今 的Object Pascal,可以說在指針運用上,絲毫不會遜色于C語言的指針。
以下內容分為八個部分,分別是 一、類型指針的定義 二、無類型指針的定義 三、指針的解除引用 四、取地址(指針賦值) 五、指針運算 六、動態內存分配 七、字符數組的運算 八、函數指針
一、類型指針的定義。對于指向特定類型的指針,在C中是這樣定義的: int *ptr; char *ptr; 與之等價的Object Pascal是如何定義的呢? var ptr : ^Integer; ptr : ^char; 其實也就是符號的差別而已。
二、無類型指針的定義。C中有void *類型,也就是可以指向任何類型數據的指針。Object Pascal為其定義了一個專門的類型:Pointer。于是, ptr : Pointer; 就與C中的 void *ptr; 等價了。
三、指針的解除引用。要解除指針引用(即取出指針所指區域的值),C 的語法是 (*ptr),Object Pascal則是 ptr^。
四、取地址(指針賦值)。取某對象的地址并將其賦值給指針變量,C 的語法是 ptr = &Object; Object Pascal 則是 ptr := @Object; 也只是符號的差別而已。
五、指針運算。在C中,可以對指針進行移動的運算,如: char a[20];?? char *ptr=a;?? ptr++; ptr+=2; 當執行ptr++;時,編譯器會產生讓ptr前進sizeof(char)步長的代碼,之后,ptr將指向a[1]。ptr+=2;這句使得ptr前進兩 個sizeof(char)大小的步長。同樣,我們來看一下Object Pascal中如何實現: 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;
六、動態內存分配。C中,使用malloc()庫函數分配內存,free()函數釋放內存。如這樣的代碼: 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中,動態分配內存的函數是GetMem(),與之對應的釋放函數為FreeMem()(傳統Pascal中獲取內存的函數是New()和 Dispose(),但New()只能獲得對象的單個實體的內存大小,無法取得連續的存放多個對象的內存塊)。因此,與上面那段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版本的),都要注意一個問題,就是分配內存的單位是字節(BYTE),因此在使用GetMem時,其第二個參數如果想當然的寫成 20,那么就會出問題了(內存訪問越界)。因為GetMem(ptr, 20);實際只分配了20個字節的內存空間,而一個整形的大小是四個字節,那么訪問第五個之后的所有元素都是非法的了(對于malloc()的參數同 樣)。
七、字符數組的運算。C語言中,是沒有字符串類型的,因此,字符串都是用字符數組來實現,于是也有一套str打頭的庫函數以進行字符數組的運算,如以下代碼: char str[15]; char *pstr; strcpy(str, "teststr"); strcat(str, "_testok"); pstr = (char*) malloc(sizeof(char) * 15); strcpy(pstr, str); printf(pstr); free(pstr); 而在Object Pascal中,有了String類型,因此可以很方便的對字符串進行各種運算。但是,有時我們的Pascal代碼需要與C的代碼交互(比如:用 Object Pascal的代碼調用C寫的DLL或者用Object Pascal寫的DLL準備允許用C寫客戶端的代碼)的話,就不能使用String類型了,而必須使用兩種語言通用的字符數組。其實,Object Pascal提供了完全相似C的一整套字符數組的運算函數,以上那段代碼的Object Pascal版本是這樣的: var str : array [1..15] of char; ? pstr : PChar; //Pchar 也就是 ^Char begin ? StrCopy(@str, 'teststr'); //在C中,數組的名稱可以直接作為數組首地址指針來用 ????????? //但Pascal不是這樣的,因此 str前要加上取地址的運算符 ? StrCat(@str, '_testok'); ? GetMem(pstr, sizeof(char) * 15); ? StrCopy(pstr, @str); ? Write(pstr); ? FreeMem(pstr); end;
八、函數指針。在動態調用DLL中的函數時,就會用到函數指針。假設用C寫的一段代碼如下: typedef int (*PVFN)(int); //定義函數指針類型 int main() { ? HMODULE hModule = LoadLibrary("test.dll"); PVFN pvfn = NULL; ? pvfn = (PVFN) GetProcAddress(hModule, "Function1"); ? pvfn(2); ? FreeLibrary(hModule); } 就我個人感覺來說,C語言中定義函數指針類型的typedef代碼的語法有些晦澀,而同樣的代碼在Object Pascal中卻非常易懂: type PVFN = Function (para : Integer) : Integer; var ? fn : PVFN; ??? //也可以直接在此處定義,如:fn : function (para:Integer):Integer; ? hm : HMODULE; begin ? hm := LoadLibrary('test.dll'); ? fn := GetProcAddress(hm, 'Function1'); ? fn(2); ? FreeLibrary(hm); end;
事件是什么 事件也是指針, 我們可以這樣申明 type ? OnMouseOn=procedure of object;//使用object關鍵字定義一個 過程或者函數的指針,讓他來關聯事件 ? TClass1=class ??? public ????? OnMouse:procedure of object; ??? end; ?? 如果寫成 ??? class.onmouse:=form1.onmousedown//這里進行了過程指針指向了。form1的一個具體事件的
?? 指針詳細。指針的表達方法 ?? ?? Const ????? const PI: ^Integer = @I;
??? ^integer=@I=Pointer=@MyProc ???? 都是指針 ??? 而 ????? Data^是指針的具體內容。
請舉例如何定義指針常量和常量指針
? 這是一個標準的Const Pointer的例子:
var ? A:Integer=100; const ? PA:PInteger=@A; procedure TForm1.Button1Click(Sender: TObject); begin ? Caption:=IntToHex(Integer(PA),8); end;
? 下面是一個用函數來模擬無法預先決定值的常量指針的例子:
Unit A; interface function PointerA:Pointer; implementation var ? ObjA:TXXX; //ObjA運行后才能被動態的創建 function PointerA:Pointer; begin ? Result:=@ObjA; end; ...
? 這樣,在UnitA之外的地方,PointerA地返回值就是常量了:)
轉載于:https://www.cnblogs.com/netilu/archive/2013/01/06/2847057.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
- 上一篇: DICOM 开发工具总结
- 下一篇: css做圆角