首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 類型轉換完全指南:數值、字符串、指針、數組與字符集的轉換規則與陷阱

     編輯:Delphi

強類型本質

Delphi 是強類型靜態語言,賦值符 := 要求左右類型**嚴格兼容**。不同於 C/C++ 隱式轉換,Delphi 需顯式調用轉換函數/類型轉換運算符,否則編譯報錯 「Type mismatch」 或運行時觸發範圍檢查錯誤。

一、數值類型轉換 (標準函數)

目標類型函數/語法示例說明
IntegerInteger(expr) / Trunc/RoundInteger('A') = 65字符/枚舉/布爾 → 序數值。浮點截斷取整。
CharChar(code)Char(65) = 'A'序數值 → 字符 (AnsiChar/WideChar 視編譯器版本)。
BooleanBoolean(expr)Boolean(0)=False, Boolean(1)=True0→False,非0→True。同 WordBool/LongBool (2/4 字節)。
String (10進制)IntToStr(int)IntToStr(15) = '15'整數 → 字符串。
String (16進制)IntToHex(int, digits)IntToHex(15,4) = '000F'固定寬度十六進制。
Pointer → IntegerInteger(@Var) / PtrInt(@Var)Integer(@Buffer)地址轉整數。64位用 NativeInt/PtrInt。

二、數值「拆分」與「合成」 (底層操作)

// 32位長整型拆分
HiWord(LongintVar)  // 高 16 位 (Word)
LoWord(LongintVar)  // 低 16 位 (Word)

// 16位整型拆分
HiByte(IntegerVar)  // 高 8 位 (Byte)
LoByte(IntegerVar)  // 低 8 位 (Byte)

// 指釖/地址拆分 (16位段:偏移模式,僅實模式/兼容層相關)
SelectorOf(Pointer) // 段選擇子 (高 16 位)
OffsetOf(Pointer)   // 偏移量 (低 16 位)

// 合成指釖 (實模式巨型指釖)
Ptr(Seg, Ofs: Word) // 相當於 C 的 MK_FP(Seg, Ofs)

// 實際應用:讀取 Windows 內部 Task Database 結構
var P: PByte; Ch: Char;
P := Ptr(GetCurrentTask, $FA); Ch := Char(P^); // 'T'
P := Ptr(GetCurrentTask, $FB); Ch := Char(P^); // 'D'

三、字符串、字符數組、PChar 三者關系與轉換 (核心難點)

1. 內存佈局差異

類型長度存儲終止符賦值方式下標 0 含義
string (AnsiString/UnicodeString)隱式 (引用計數、長度字段)**自動管理**,通常以 #0 結尾 (供 API 用)s := 'abc'不可訪問 (編譯錯誤) 或返回長度 (舊版 ShortString)
array[0..N] of Char無**手動** 需以 #0 結尾StrPCopy(arr, 'abc') 或逐字符賦值第一個字符
array[1..N] of Char無**手動** 需以 #0 結尾StrPCopy(@arr[1], 'abc')越界 (無效)
PChar (^Char)無指向以 #0 結尾的緩衝區p := @str[1] (舊版) / PChar(str) (新版)指向首字符

2. 關鍵轉換函數

  • StrPCopy(Dest: PChar; Source: string): PChar:複製字符串到緩衝區,**自動添加 #0 結尾**。返回 Dest。
  • StrPas(Source: PChar): string:從 #0 終止的 PChar 複製到新 string。
  • PChar(string) (Delphi 2009+):獲取字符串內部緩衝區指針 (只讀),已保證 #0 結尾。
  • string(PChar):從 PChar 創建 string (按 #0 截斷)。

3. 經典錯誤示範與正確寫法

// 錯誤 1: 直接將 string 當 PChar 用且未確保 #0 結尾 (舊版 ShortString)
var s: string; p: PChar;
s := 'new'; p := @s[1]; // s[0] 存長度 3,內存為 'n','e','w' 無 #0
ShowMessage(StrPas(p)); // 讀越界,亂碼或崩潰

// 正確 1: 手動加 #0 (舊版技巧)
s := 'new' + #0; p := @s[1]; // 內存: 'n','e','w',#0
ShowMessage(StrPas(p)); // 正常

// 正確 2: 用 StrPCopy 自動加 #0
StrPCopy(@s[1], 'new'); // s 變為 'new'#0, 長度 4
ShowMessage(StrPas(@s[1]));

// 正確 3: Delphi 2009+ 直接用 PChar(s)
var s: string; p: PChar;
s := '新'; p := PChar(s); // 內部緩衝區已有 #0
ShowMessage(string(p)); // 正常

// 字符數組陷阱
var a: array[1..10] of Char; b: array[0..10] of Char;
StrPCopy(@a[1], 'abc'); // 正確,@a[1] 是首字符地址
StrPCopy(a, 'abc');     // 錯誤!a 退化為指針指向 a[1]? 實際 a 是整個數組地址,類型不匹配
StrPCopy(b, 'abc');     // 正確,b 即 @b[0]
StrPCopy(@b[0], 'abc'); // 正確,等價

四、Unicode 時代 (Delphi 2009+) 的新規則

  • string = UnicodeString (UTF-16),Char = WideChar (2 字節)。
  • PChar = PWideChar。Windows API 調用優先用 W 版 (MessageBoxW) 直接傳 PChar。
  • ANSI 交互:顯式用 AnsiString/UTF8String/RawByteString,配合 TEncoding 轉換。
  • SizeOf(Char) = 2,Length(s) 返回字符數 (碼元數),字節長度 = Length(s) * SizeOf(Char)。
  • 遍歷字符:for c in s do ... (c: Char) 或 for i := 1 to Length(s) do s[i]。**勿用字節偏移訪問**。

五、最佳實踐檢查表

  1. **API 調用**:參數類型嚴格匹配 (DWORD/Longint、PChar/PAnsiChar、構構體對齊)。
  2. **文件/網絡/數據庫**:明確編碼 (UTF-8/ANSI),用 TEncoding 或 AnsiString 類型標記。
  3. **指針運算**:用 PByte/Pointer 做字節運算,避免 PChar 因字符大小導致錯誤偏移。
  4. **字符串拼接/格式化**:優先用 Format/TStringBuilder,避免隱式轉換驚喜。
  5. **範圍檢查**:開啟 {$R+} 捕獲數組越界、數值溢出。釋放版關閉提速。

總結

Delphi 類型轉換的核心在於**「顯式、精確、語義清晰」**。掌握 Integer/Char/Boolean 序數轉換、Hi/Lo 位拆分、string/PChar/CharArray 內存模型差異、StrPCopy/StrPas 橋接函數、以及 Unicode 時代的新類型映射,即可從容應對 99% 的類型轉換場景,編寫安全、高效、可移植的 Delphi 代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved