內存中的數(shù)據(jù)除了 0 便是 1, 你把它當作圖片、字符、數(shù)字等等, 那是你的事, 內存只認識 0 和 1. Win32 系統(tǒng)除了使用硬內存以外, 還可以從硬盤上開辟虛擬內存; 因為 Win32 的內存地址范圍在 4 個 G 以內(0..232-1), 所以它最多能夠給一個應用程序分配 4G 的運行空間; 并且其中的 2G 有系統(tǒng)管理, 實際上程序只有 2G 的自主空間. 還記得有說 String 最大長度是 2G 嗎? 就是這個道理. 有 4G 的內存, 就有 4G 個地址, 也就是最多可以有 (1024*1024*1024*4 - 1 = 4294967295) 個內存地址, 這剛好是 Delphi 中 Cardinal 的最大值, 所以 32 位的指針類型追到底都是 Cardinal 類型的一個數(shù)字. 一個內存地址是 0..4294967295 之間的一個數(shù)字, 你可以通過內存地址讀取或寫入數(shù)據(jù); 一個指針要用來索引或標識內存, 它也是 0..4294967295 之間的一個數(shù)字; 它們雖不相同, 但通過指針可以找到實際存儲數(shù)據(jù)的內存地址, 并按指定的類型去讀寫它. 譬如: var str: string; n: Cardinal; pstr: PString; begin str := 'ABCDE'; n := Cardinal(str); {獲取內存地址} pstr := @str; {現(xiàn)在 pstr 是 str 的指針} {n 與 pstr 的數(shù)字結果是(結果是隨機的, 知道不一樣就行了):} ShowMessage(IntToStr(n)); {4571092} ShowMessage(IntToStr(Cardinal(pstr))); {1244652} {但通過 pstr 可以找到 str} ShowMessage(pstr^); {ABCDE} end;程序運行后, 字符串所在的內存基本上是下面這個樣子(以字節(jié)為單位), 上例中的 n 標識著 ↓ 的位置:
換二進制圖示一下:
如果只看二進制, 這個數(shù)據(jù)到底是什么很難知道; 再說它為什么非得是字符串 "ABCDE" 呢? 這可不一定. 下面的例子中, 我們先是權且把它當作字符串, 但隨著指針的移動, 字符串也在變化. 然后, 有分別把它分別用 Byte 指針(PByte) 和 Integer 指針(PInteger) 去讀取它, 也會得到相應的值. 完整示例如下: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var str: string; ps: PChar; n: Cardinal; begin str := 'ABCDE'; ps := PChar(str); n := Cardinal(ps); //n := Cardinal(str); {這行可以代替上面兩行} ShowMessage(IntToStr(n)); {結果是 Windows 隨機管理的} ShowMessage(PChar(n)); {ABCDE} ShowMessage(PChar(n+1)); {BCDE} ShowMessage(PChar(n+2)); {CDE} ShowMessage(PChar(n+3)); {DE} ShowMessage(PChar(n+4)); {E} end; procedure TForm1.Button2Click(Sender: TObject); var str: string; n: Cardinal; pb: PByte; begin str := 'ABCDE'; n := Cardinal(str); ShowMessage(IntToStr(n)); {4571140; 這是我這里的結果, 這是隨機的} pb := PByte(n); ShowMessage(IntToStr(pb^)); {65} pb := PByte(n+1); ShowMessage(IntToStr(pb^)); {66} end; procedure TForm1.Button3Click(Sender: TObject); var str: string; n: Cardinal; pint: PInteger; begin str := 'ABCDE'; n := Cardinal(str); ShowMessage(IntToStr(n)); {4571140; 這是我這里的結果, 這是隨機的} pint := PInteger(n); ShowMessage(IntToStr(pint^)); {1145258561} pint := PInteger(n+1); ShowMessage(IntToStr(pint^)); {1162101570} end; end.上面的第三個程序段的結果或許讓你迷惑: 第一個結果, 應該和 "ABCD" 有點關系才對啊, 怎么是: 1145258561 ? 第二個結果, 應該和 "BCDE" 有點關系才對啊, 怎么是: 1162101570 ? 為什么呢? 這當然沒錯, 聽我解釋: 1145258561 轉換成十六進制是: 44434241, 寫得清楚一點是: $44 $43 $42 $41; 還記得 Intel 等當下流行的 CPU 安排數(shù)據(jù)是倒著的嗎? 自己算算下一個, 用附件中的計算器即可. |
|