2013-02-01 4 views
9

जब मैं लक्ष्य मंच 64-बिट Windows के लिए डेल्फी XE2 में निम्न कोड को संकलित ...डेल्फी XE2 64 बिट में HKEY_-Constants के लिए मुझे "निरंतर अभिव्यक्ति subrange सीमाओं का उल्लंघन क्यों करती है"?

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_-स्थिरांक की प्रत्येक के लिए चेतावनी मिलती है: "W1012 लगातार अभिव्यक्ति subrange का उल्लंघन करती है

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

ये मेरे लिए ठीक लग: सीमा "

मैं (पहचानकर्ता पर Ctrl + Leftclick के साथ) Winapi.Windows में घोषणाओं की जाँच की। संकलक अभी भी क्यों सोचता है कि कोई समस्या है?

+0

लगता है कि व्यवहार्य लगता है, तो अगर समाधान के बजाय समाधान का उपयोग करना होगा? – dummzeuch

+4

दस्तावेज़ ['# Case_Statements'] से निकालें [http://docwiki.embarcadero.com/RADStudio/XE3/en/Declarations_and_Statements#Case_Statements):" .. जहां selectorExpression 32 बिट्स (स्ट्रिंग) से छोटे क्रमिक प्रकार की कोई अभिव्यक्ति है 32 बिट्स से बड़े प्रकार के नियम और टर्मिनल अमान्य हैं)। " –

+1

@LURD मैं सटीक के लिए XE3 दस्तावेज़ नहीं लेगा, जब यह 64 बिट (और यहां तक ​​कि CrossPlatform) से संबंधित है। यह नए लक्ष्यों के लिए बहुत निराश है, और इसे रीफ्रेश नहीं किया गया है (आपके पास अभी भी "लिनक्स" संदर्भ हैं, और Win32 विशिष्ट विवरण - देखें [उदाहरण के लिए यह पृष्ठ] (http://docwiki.embarcadero.com/RADStudio/XE3/en/ Program_Control))। लेकिन इस मामले में, वास्तविक सीमा की तरह लगता है - भले ही यह अनिवार्य नहीं है, जेनरेट एएसएम बिंदु से, 64 बिट में, आप 'केस' की जांच के लिए बैकएंड पर x64 रजिस्टरों का उपयोग कर सकते हैं। तो मुझे लगता है कि 64 बिट संदर्भ के लिए संकलक फ्रंटेंड अपडेट नहीं किया गया था। –

उत्तर

8

64 बिट संकलक HKEY_CLASSES_ROOT के वास्तविक मूल्य है पर:

FFFFFFFF80000000 

क्योंकि Integer लिए डाली एक ऋणात्मक संख्या में 80000000 बनाता है यही कारण है कि। और फिर हस्ताक्षर किए गए रूपांतरण को FFFFFFFF80000000 पर ले जाता है। ध्यान दें कि यह मान सही है। खिड़कियों हेडर फाइल में घोषणा है:

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

और जब आप हेडर फाइल शामिल हैं और एक सी ++ प्रोग्राम में HKEY_CLASSES_ROOT का मूल्य का निरीक्षण किया, यह डेल्फी घोषणा के लिए के रूप में ठीक उसी मूल्य है।

और फिर हम डेल्फी प्रलेखन जिसमें कहा गया है कि selectors in a case statement can only be से पहेली को हल कर सकते हैं:

एक क्रमसूचक प्रकार के किसी भी अभिव्यक्ति से छोटी 32 बिट

आप कोई चारा नहीं बदलने के लिए case कथन if कथन के साथ।

+0

मुझे खेद है, लेकिन * आपके पास 'HKEY_ *' स्थिरांक के सीमित संभावित मानों के कारण 'केस' का उपयोग करने के लिए विकल्प * है। ऊपर मेरा जवाब और टिप्पणियां देखें। –

+0

यदि आप नाटक करना चाहते हैं कि HKEYs 32 बिट चौड़े हैं और गैर-पूर्वनिर्धारित कुंजी के साथ झूठी सकारात्मकताओं का जोखिम चलाते हैं तो आप अर्नुद कहते हैं। लेकिन यह कोड करने का एक भयानक तरीका है। कार्यान्वयन के विवरण पर निर्भर करते हुए और 32 बिट्स को 64 बिट मानों को कम करना। मैं इसके बारे में सोचने के बारे में चिंतित हूं। –

1

HKEY=UINT_PTR आपके मामले में एक हस्ताक्षरित 64 बिट पूर्णांक है, और case ... of कथन इसे संभालने के लिए प्रतीत नहीं होता है।

XE2/XE3 संकलक सामने के अंत अभी भी भले ही संकलक बैक-एंड (क्लासिक sub register,constant; jz @... एएसएम कोड पीढ़ी पैटर्न के साथ 64 बिट मामले बयान को संभालने में सक्षम नहीं करने के लिए कोई तकनीकी कारण है मान लिया गया है कि यह एक 32 बिट मंच लक्षित करता है,)।

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

यह काम करेंगे विंडोज के तहत: HKEY_* स्थिरांक की सीमित संख्या के कारण, मुझे लगता है कि आप _HKey मान के अधिकतम 32 बिट्स को अनदेखा कर सकते हैं, और इसलिए बग्गीका उपयोग करेंकथन। और यह Win32 और Win64 दोनों के लिए निश्चित रूप से काम करेगा।

मुझे संदेह है कि ... 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 
.... 

मुझे लगता है कि पिछले एक पसंद किया जाता है, और आधुनिक पाइपलाइनों सीपीयू के साथ नहीं धीमी,।

+0

'HKEY_CLASSES_ROOT32' का मान' 0000000080000000' है और यह गलत है। यह 'एफएफएफएफएफएफएफएफ 80000000' होना चाहिए। –

+0

@ डेविड हेफरनन बेशक, लेकिन '_HKey' पैरामीटर को' फ़ंक्शन HKeyToString (_HKey: integer) में 'पूर्णांक' के रूप में फिर से परिभाषित किया गया है: स्ट्रिंग; ', यदि' HKEY_CLASSES_ROOT32' मान से मेल खाएगा, तो बस ऊपरी DWord को अनदेखा कर देगा मूल 'HKey' मान। यह विंडोज के तहत अपेक्षित के रूप में काम करेगा: 'HKEY_ *' स्थिरांक की सीमित संख्या के कारण, मुझे लगता है कि आप '_HKey' मान के अधिकतम 32 बिट्स को अनदेखा कर सकते हैं, और इसलिए बग्गी' केस _HKey का उपयोग करें ... ' बयान। –

+0

यह एक सूचक के शीर्ष 32 बिट्स को अनदेखा करने जैसा है। रुको जब तक RegOpenKeyEx आपको उच्च बिट सेट के साथ एक HKEY देता है। –

संबंधित मुद्दे