簡體   English   中英

為什么在Delphi XE2 64bit中為HKEY_常量獲得“常量表達式違反子范圍邊界”?

[英]Why do I get “Constant expression violates subrange bounds” for HKEY_-constants in Delphi XE2 64bit?

當我在Delphi XE2中為目標平台64位Windows編譯以下代碼時......

function HKeyToString(_HKey: HKey): string;
begin
  case _HKey of
    HKEY_CLASSES_ROOT: result := 'HKEY_CLASSES_ROOT'; // do not translate
    HKEY_CURRENT_USER: result := 'HKEY_CURRENT_USER'; // do not translate
    HKEY_LOCAL_MACHINE: result := 'HKEY_LOCAL_MACHINE'; // do not translate
    HKEY_USERS: result := 'HKEY_USERS'; // do not translate
    HKEY_PERFORMANCE_DATA: result := 'HKEY_PERFORMANCE_DATA'; // do not translate
    HKEY_CURRENT_CONFIG: result := 'HKEY_CURRENT_CONFIG'; // do not translate
    HKEY_DYN_DATA: result := 'HKEY_DYN_DATA'; // do not translate
  else
    Result := Format(_('unknown Registry Root Key %x'), [_HKey]);
  end;
end;

...我收到每個HKEY_-Constants的警告:“W1012常量表達式違反了子范圍”

我檢查了Winapi.Windows中的聲明(使用Ctrl + Leftclick標識符):

type
  HKEY = type UINT_PTR;
{...}
const
  HKEY_CLASSES_ROOT     = HKEY(Integer($80000000));

這對我來說很好看。 為什么編譯器仍然認為存在問題?

在64位編譯器上, HKEY_CLASSES_ROOT的實際值是:

FFFFFFFF80000000

這是因為對Integer 80000000轉換使得80000000成為負數。 然后轉換為無符號導致FFFFFFFF80000000 請注意,此值是正確的。 Windows頭文件中的聲明是:

#define HKEY_CLASSES_ROOT (( HKEY ) (ULONG_PTR)((LONG)0x80000000) )

當您在C ++程序中包含頭文件並檢查HKEY_CLASSES_ROOT的值時,它與Delphi聲明的值完全相同。

然后我們可以從Delphi文檔中解決這個難題,該文檔指出case語句中的選擇器只能是

任何小於32位的序數類型的表達式

您別無選擇,只能用if語句替換case語句。

在你的情況下, HKEY=UINT_PTR是一個無符號的64位整數,並且case ... of語句似乎沒有處理它。

XE2 / XE3編譯器前端仍假設它以32位平台為目標,即使編譯器后端沒有技術原因也無法處理64位案例語句(使用經典sub register,constant; jz @...匯編代碼生成模式)。

您可以嘗試將所有內容轉換為integer

const
  HKEY_CLASSES_ROOT32 = Integer($80000000);

...

function HKeyToString(_HKey: integer): string;
begin
  case _HKey of
    HKEY_CLASSES_ROOT32: result := 'HKEY_CLASSES_ROOT'; // do not translate
 ...

或者只是忽略_HKey值的最高32位(這是相同的):

function HKeyToString(_HKey: HKey): string;
begin
  case _HKey and $ffffffff of
    HKEY_CLASSES_ROOT and $ffffffff: result := 'HKEY_CLASSES_ROOT'; // do not translate
 ...

它將在Windows下按預期工作:由於HKEY_*常量的數量有限,我認為你可以忽略 _HKey的最高32位 ,因此使用case .. of...語句的錯誤case .. of... 它當然適用於Win32和Win64。

我甚... and $f懷疑... and $f就夠了 - 看看所有的HKEY_*常量。

最后(當然最好的解決方案)是使用好的舊嵌套if... else if...語句:

function HKeyToString(_HKey: HKey): string;
begin
  if_HKey=HKEY_CLASSES_ROOT then
    result := 'HKEY_CLASSES_ROOT' else // do not translate
  if_HKey=HKEY_CURRENT_USER then
    result := 'HKEY_CURRENT_USER' else // do not translate
 ....

我想最后一個是首選,而不是更慢,使用現代管道CPU。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM