2015-04-22 28 views
11

एक आवश्यकता में मुझे "जेनेरिक" पॉइंटर के मूल्य को संग्रहीत करने की आवश्यकता को देखते हुए और पॉइंट-इन मेमोरी में कोई दिलचस्पी नहीं है, मुझे इसे की तुलना में intptr_t के रूप में स्टोर करने के लिए अधिक अर्थपूर्ण रूप से सही लगता है। सवाल यह है कि uintptr_t बेहतर अनुकूल है या नहीं, और जब किसी को आम तौर पर दूसरे पर प्राथमिकता दी जाती है?intptr_t पर uintptr_t को कब पसंद किया जाता है?

+4

उम्म .. क्या यह शून्य नहीं है? – mjs

+1

मैं नहीं चाहता कि इस संरचना के क्लाइंट कभी भी सोचें कि _pointee_ मान किसी भी ब्याज का है, और फ़ील्ड को 'intptr_t' या' uintptr_t' बनाकर मैं यह स्पष्ट करने की आशा करता हूं कि यह _pointer_ value है दिलचस्प। कृपया मुझे बताएं कि क्या मैं गलत पेड़ को तर्क में डाल रहा हूं :-) –

+2

यह आपकी व्याख्या है: अन्य शायद यह भी नहीं जानते कि 'intptr_t' क्या है। मैं केवल 'शून्य *' और एक * टिप्पणी * का उपयोग करता हूं, यह इंगित करने के लिए कि आप केवल स्मृति पते की परवाह करते हैं। कुछ ऐसा: 'शून्य * पता;/* हम सिर्फ स्मृति पते */'के बारे में परवाह करते हैं। – edmz

उत्तर

7

यह ज्यादातर स्टाइलिस्ट तर्क है (एक अनुकूलन संकलक शायद समान, या बहुत समान कोड उत्पन्न करेगा)। हालांकि, सूचक तुलना एक मुश्किल मुद्दा हो सकता है।

शुद्ध रूप से मानक सी पॉइंटर तुलना की तुलना में याद रखें केवल समान कुल डेटा के पॉइंटर्स के लिए लगभग सार्थक है। आपको शायद malloc से दो परिणामों की तुलना करने की अनुमति नहीं है, उदा। पॉइंटर्स की एक क्रमबद्ध सरणी रखने के लिए।

मैं उन्हें void*, या अन्य uintptr_t के रूप में रखूंगा। हस्ताक्षर किए गए intptr_t में नकारात्मक और सकारात्मक संख्याओं को सीग्रेग करने की असुविधा होती है, और जहां वे महत्वपूर्ण एप्लिकेशन पॉइंटर्स से आ रहे हैं, शायद इसका स्वागत नहीं है।

सूचना है कि एक void* dereferenced नहीं किया जा सकता: एक uintptr_t के रूप में, आप यह कुछ डेटा पते से बताया के साथ उपयोगी करने के लिए कास्ट करने के लिए है; हालांकि void* पॉइंटर्स memset

पीएस जैसे दिनचर्या को पारित किया जा सकता है। मैं एक साधारण वर्चुअल एड्रेस स्पेस के साथ एक सामान्य प्रोसेसर (उदा। कुछ x86, पावरपीसी, एआरएम, ...) मान रहा हूं। आप मिल सकता है विदेशी प्रोसेसर -कुछ DSPs बहुत महत्वपूर्ण अंतर के साथ perhaps- (और शायद जिस पर intptr_t हमेशा सार्थक है, जो 1990 के दशक Cray Y-MP सुपर कंप्यूटर sizeof(long*) != sizeof(char*) पर याद; उस समय C99 मौजूद नहीं था, और मुझे यकीन है कि नहीं कर रहा हूँ अपने <stdint.h> सकता है ऐसी मशीनों पर सार्थक हो)

+0

मैंने यूनिकोस चलाने वाले क्रे T90 पर काम किया।'लंबा *' और 'char *' एक ही आकार (64 बिट्स) थे, लेकिन 'char *' ने बाइट ऑफ़सेट स्टोर करने के लिए उच्च-आदेश 3 बिट्स का उपयोग किया, क्योंकि मशीन पते 64-बिट शब्दों की ओर इशारा करते थे (यह सब प्रबंधित था सॉफ्टवेयर में)। क्या पुराना वाई-एमपी अलग था? –

+0

मैं विवरण भूल गया, लेकिन कास्टिंग (मैं किस दिशा में भूल गया) '(char *)' से/('* * 'से एक मुद्दा था ... –

+2

टी 0 9 पर, पूर्णांक और सूचक रूपांतरणों ने बस बिट्स की प्रतिलिपि बनाई। यदि 'char *' पॉइंटर में गैर-शून्य ऑफसेट होता है, तो इसे 'लम्बा *' में परिवर्तित करने से एक अमान्य सूचक मिलेगा, क्योंकि 3 उच्च-आदेश बिट्स पते का हिस्सा होंगे (और वास्तविक पता स्थान लगभग नहीं था वह बड़ा)। मैंने एक बार कुछ कोड देखा जो दो पॉइंटर्स के बीच अंतर को पहले पूर्णांक में परिवर्तित करके गणना करता था; मैंने इंगित किया कि प्रत्यक्ष सूचक घटाव सरल है और वास्तव में काम करने का गुण है। –

9

यह बहुत अजीब लगता है, क्योंकि इसे केस्टों की आवश्यकता होगी। सी में void * का बड़ा लाभ है कि यह बिना किसी बगैर अन्य ऑब्जेक्ट पॉइंटर प्रकारों में/से परिवर्तित होता है, जो कि रास्ता साफ है।

कहा गया है कि uintptr_t यह समझ सकता है कि क्या आप पॉइंटर के बिट्स को चीजें करना चाहते हैं, जो आप एक हस्ताक्षरित पूर्णांक (उदाहरण के लिए, दाईं ओर स्थानांतरित करने के साथ) के रूप में समझदारी से नहीं कर सकते हैं।

+0

_ "यह बहुत अजीब लगता है, क्योंकि इसे casts की आवश्यकता होगी" _ - ठीक है, हाँ। मैं नहीं चाहता कि इस स्ट्रक्चर के क्लाइंट कभी भी सोचें कि _pointee_ मान किसी भी ब्याज का है, और फ़ील्ड को 'intptr_t' या' uintptr_t' बनाकर मैं यह स्पष्ट करना चाहता हूं कि यह _pointer_ value है जो दिलचस्प है । कृपया मुझे बताएं कि क्या मैं गलत पेड़ को तर्क में डाल रहा हूं :-) –

+2

@ जोहान गेलल निश्चित रूप से निश्चित होना मुश्किल है। लेकिन चूंकि 'शून्य *' का पूरा बिंदु यह है कि इसे संदर्भित नहीं किया जा सकता है क्योंकि पॉइंट के बारे में कोई जानकारी नहीं है, मैं कहूंगा कि यह वही है जो पहले से ही संचार करता है। – unwind

+0

आपको [x86_64 कैनोलिक पतों पर हस्ताक्षरित एक्सटेंशन] प्राप्त करने के लिए 'intptr_t' का उपयोग करने की आवश्यकता हो सकती है (http://stackoverflow.com/q/16198700/995714) –

0

यदि आप अंकगणितीय रूप से मान को जोड़ना चाहते हैं (उदा।, इसे एन्क्रिप्ट करने के लिए), तो आपके पास एक हस्ताक्षरित प्रकार (जहां अंकगणित ओवरफ्लो अपरिभाषित व्यवहार देता है) के साथ एक हस्ताक्षरित प्रकार (जहां अंकगणित लपेटें) के साथ अधिक लचीलापन है।

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