![](/img/trans.png)
[英]E1012 Constant expression violates subrange bounds error in Delphi XE4
[英]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.