2013-02-01 8 views
9

Kiedy skompilować następujący kod w Delphi XE2 dla platformy docelowej 64-bitowym systemie Windows ...Dlaczego otrzymuję komunikat "Stałe wyrażenie narusza zakresy podzakresów" dla stałych HKEY w Delphi XE2 64bit?

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; 

... dostaję ostrzeżenia dla każdego z HKEY_-Stałe: „W1012 Stała ekspresja jest niezgodny podzakresu granice”

Sprawdziłem oświadczenia w Winapi.Windows (z Ctrl + Leftclick dotyczące identyfikatorów):

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

te wyglądają dobrze na mnie. Dlaczego kompilator nadal uważa, że ​​jest jakiś problem?

+0

Brzmi prawdopodobne, więc rozwiązaniem byłoby użyć instrukcji zamiast? – dummzeuch

+4

Wyciąg z doc ['# Case_Statements'] (http://docwiki.embarcadero.com/RADStudio/XE3/en/Declarations_and_Statements#Case_Statements):" .. gdzie selectorExpression to dowolne wyrażenie typu porządkowego mniejsze niż 32 bity (ciąg znaków typy i liczby porządkowe większe niż 32 bity są nieprawidłowe). " –

+1

@LURD Nie będę pobierał dokumentacji XE3 w celu uzyskania dokładności, jeśli dotyczy ona 64-bitowego (a nawet CrossPlatform). Jest dość przestarzały w przypadku nowych celów i nie został odświeżony (nadal masz odniesienia do "Linuksa" i opisy specyficzne dla systemu Win32 - patrz [np. Ta strona] (http://docwiki.embarcadero.com/RADStudio/XE3/en/ Program_Control)). Ale w tym przypadku brzmi jak prawdziwe ograniczenie - nawet jeśli nie jest to obowiązkowe, z wygenerowanego punktu widzenia, ponieważ w 64-bitowym można użyć rejestrów x64 na zapleczu, aby sprawdzić "przypadek". Więc domyślam się, że nakładka kompilatora nie została zaktualizowana dla kontekstu 64-bitowego. –

Odpowiedz

8

Na 64-bitowym kompilatorem rzeczywista wartość HKEY_CLASSES_ROOT jest:

FFFFFFFF80000000 

To dlatego, że obsada do Integer sprawia 80000000 do liczby ujemnej. A następnie konwersja na niepodpisane prowadzi do FFFFFFFF80000000. Zwróć uwagę, że ta wartość jest prawidłowa. Deklaracja w pliku nagłówka okna wynosi:

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

a kiedy dołączyć plik nagłówka i sprawdzić wartość HKEY_CLASSES_ROOT w programie C++, to jest dokładnie taka sama jak wartość dla deklaracji Delphi.

A potem możemy rozwiązać zagadkę z dokumentacją Delphi, który stwierdza, że ​​selectors in a case statement can only be:

każde wyrażenie typu porządkowej mniejszy niż 32 bitów

Nie masz wyboru, ale do zastąpienia Twoje oświadczenie case z instrukcją if.

+0

Przykro mi, ale * masz wybór * do użycia 'case', ze względu na ograniczone możliwe wartości stałych' HKEY_ * '. Zobacz moją odpowiedź i komentarze powyżej. –

+0

Jeśli chcesz udawać, że klucze HKEY mają szerokość 32 bitów i narażasz się na fałszywe alarmy za pomocą nieokreślonych kluczy, to to, co mówi Arnaud. Ale to okropny sposób kodowania. Poleganie na szczegółach implementacji i obcinaniu 64-bitowych wartości do 32 bitów. Jestem przerażony na samą myśl o tym. –

1

HKEY=UINT_PTR to niepodpisana 64-bitowa liczba całkowita w twoim przypadku, a instrukcja case ... of wydaje się nie obsługiwać tego.

Front-end kompilatora XE2/XE3 nadal zakłada, że ​​jest on przeznaczony dla platformy 32-bitowej, nawet jeśli nie ma technicznych przyczyn, dla których back-end kompilatora nie byłby w stanie obsłużyć 64-bitowych instrukcji case (z klasycznym kodem generującym ASM wzór sub register,constant; jz @...).

Można spróbować typecast wszystko 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 
... 

lub po prostu zignorować upmost 32 bity wartości _HKey (to samo):

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

Będzie ona działać zgodnie z oczekiwaniami pod Windows: ze względu na ograniczoną liczbę stałych HKEY_*, można po prostu zignorować maksymalnie 32 bitów z wartości _HKey, a zatem korzystać z buggy case .. of... oświadczenie. I będzie działać oczywiście zarówno dla Win32 jak i Win64.

Podejrzewam, że wystarczy ... and $f - zobacz wszystkie stałe HKEY_*.

Ostatni (a na pewno najlepszym rozwiązaniem) jest wykorzystanie starych, dobrych zagnieżdżone if... else if... oświadczenia:

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 
.... 

Chyba ostatnia jest korzystne, a nie wolniej, z nowoczesnych rurociągów procesorów.

+0

Wartość 'HKEY_CLASSES_ROOT32' wynosi' 0000000080000000' i jest niepoprawna. Musi to być "FFFFFFFF80000000". –

+0

@DavidHeffernan Oczywiście, ale ponieważ parametr '_HKey' został przedefiniowany jako' integer' w 'function HKeyToString (_HKey: integer): string;', jeśli będzie pasował do 'HKEY_CLASSES_ROOT32' wartości, po prostu ignorując górny DWORD oryginalna wartość 'HKey'. Będzie działał zgodnie z oczekiwaniami w systemie Windows: ze względu na ograniczoną liczbę stałych 'HKEY_ *', myślę, że możesz po prostu zignorować maksymalnie 32 bity wartości '_HKey', a zatem użyć błędnego' przypadku _HKey z ... ' komunikat. –

+0

To jak ignorowanie 32 najlepszych bitów wskaźnika. Poczekaj, aż RegOpenKeyEx poda ci zestaw HKEY z wysokim bitem. –

Powiązane problemy