क्या है uintptr_t
और इसका क्या उपयोग किया जा सकता है?
क्या है uintptr_t
और इसका क्या उपयोग किया जा सकता है?
जवाबों:
uintptr_t
एक अहस्ताक्षरित पूर्णांक प्रकार है जो डेटा पॉइंटर को संग्रहीत करने में सक्षम है। जिसका आमतौर पर मतलब है कि यह एक पॉइंटर के समान आकार है।
यह वैकल्पिक रूप से C ++ 11 और बाद के मानकों में परिभाषित किया गया है।
किसी पूर्णांक प्रकार को प्राप्त करने का एक सामान्य कारण जो आर्किटेक्चर के पॉइंटर प्रकार को धारण कर सकता है, वह है पॉइंटर पर पूर्णांक-विशिष्ट संचालन करना, या एक पूर्णांक "हैंडल" के रूप में प्रदान करके पॉइंटर के प्रकार को अस्पष्ट करना।
संपादित करें: ध्यान दें कि स्टीव जेसप के पास कुछ और दिलचस्प विवरण हैं (जो मैं चोरी नहीं करूंगा) एक अन्य उत्तर में आपके लिए पांडित्यपूर्ण प्रकार :)
size_t
केवल सबसे बड़ी वस्तु के आकार को रखने के लिए पर्याप्त होना चाहिए, और एक सूचक से छोटा हो सकता है। यह 8086 (16 बिट्स size_t
, लेकिन 32 बिट्स void*
) जैसे खंडित वास्तुशिल्प पर अपेक्षित होगा
ptrdiff_t
। uintptr_t
उस के लिए नहीं है।
unsigned int
आमतौर पर पर्याप्त बड़ा नहीं है। लेकिन यह काफी बड़ा हो सकता है। यह प्रकार विशेष रूप से सभी "ग्रहण" को हटाने के लिए मौजूद है ।
पहली बात, जिस समय यह प्रश्न पूछा uintptr_t
गया था , वह C ++ में नहीं था। यह <stdint.h>
वैकल्पिक प्रकार के रूप में , C99 में है । कई C ++ 03 कंपाइलर उस फ़ाइल को प्रदान करते हैं। यह C ++ 11 में भी है <cstdint>
, जहां फिर से यह वैकल्पिक है, और जो परिभाषा के लिए C99 को संदर्भित करता है।
C99 में, इसे "संपत्ति के साथ एक अहस्ताक्षरित पूर्णांक प्रकार" के रूप में परिभाषित किया गया है कि शून्य के लिए किसी भी वैध सूचक को इस प्रकार में परिवर्तित किया जा सकता है, फिर वापस सूचक को शून्य में परिवर्तित किया जा सकता है, और परिणाम मूल सूचक के बराबर होगा।
इसका मतलब यह लो कि यह क्या कहता है। यह आकार के बारे में कुछ नहीं कहता है।
uintptr_t
एक के रूप में एक ही आकार के हो सकता है void*
। यह बड़ा हो सकता है। यह गर्भधारण करने में छोटा हो सकता है, हालांकि इस तरह का C ++ कार्यान्वयन विकृत होता है। उदाहरण के लिए, कुछ काल्पनिक प्लेटफ़ॉर्म पर जहां void*
32 बिट्स हैं, लेकिन वर्चुअल एड्रेस स्पेस के केवल 24 बिट्स का उपयोग किया जाता है, आपके पास 24-बिट हो सकता है uintptr_t
जो आवश्यकता को पूरा करता है। मुझे नहीं पता कि एक कार्यान्वयन ऐसा क्यों करेगा, लेकिन मानक इसकी अनुमति देता है।
void*
। यह संभव भविष्य की दिशाओं को प्रभावित करता है, हालांकि, खासकर यदि आप किसी ऐसी चीज का उपयोग करने के लिए बदलना चाहते हैं जो वास्तव में सिर्फ एक पूर्णांक संभालती है, तो एक परिवर्तित सूचक बिल्कुल नहीं।
typedef struct { int whyAmIDoingThis; } SeriouslyTooLong; SeriouslyTooLong whyAmNotDoneYet; whyAmINotDoneYet.whyAmIDoingThis = val; callback.dataPtr = &whyAmINotDoneYet;
। इसके बजाय: callback.dataPtr = (void*)val
। दूसरी तरफ, आप निश्चित रूप void*
से इसे प्राप्त करते हैं और इसे वापस करना पड़ता है int
।
यह एक अहस्ताक्षरित पूर्णांक प्रकार है जो एक सूचक का आकार है। जब भी आपको पॉइंटर के साथ कुछ असामान्य करने की आवश्यकता होती है - जैसे उदाहरण के लिए सभी बिट्स को उल्टा करना (यह मत पूछें कि आपने इसे क्यों डाला) uintptr_t
और इसे एक सामान्य पूर्णांक संख्या के रूप में हेरफेर करें, तो वापस डालें।
void*
पॉइंटर वैल्यू को uintptr_t
फिर से और बैक में कनवर्ट करने से ऑरिजिनल void*
पॉइंटर के बराबर की तुलना में वैल्यू मिलती है। uintptr_t
आमतौर पर इसका आकार एक जैसा होता है void*
, लेकिन इसकी कोई गारंटी नहीं है, न ही कोई गारंटी है कि परिवर्तित मूल्य के बिट्स का कोई विशेष अर्थ है। और इस बात की कोई गारंटी नहीं है कि यह बिना सूचना के नुकसान के एक परिवर्तित पॉइंटर-टू-फंक्शन वैल्यू को होल्ड कर सकता है। अंत में, यह मौजूद होने की गारंटी नहीं है।
"क्या uintptr_t डेटा प्रकार है" भाग के लिए पहले से ही कई अच्छे उत्तर हैं। मैं "इसका क्या उपयोग किया जा सकता है?" इस पोस्ट में हिस्सा।
मुख्य रूप से संकेत पर बिटवाइज़ संचालन के लिए। याद रखें कि C ++ में पॉइंटर्स पर बिटवाइज़ ऑपरेशन नहीं कर सकते हैं। कारणों से देखें कि आप C में पॉइंटर पर बिटवाइज़ ऑपरेशन क्यों नहीं कर सकते, और क्या इसके आसपास कोई रास्ता है?
इस प्रकार पॉइंटर्स पर बिटवाइज़ ऑपरेशंस करने के लिए किसी को पॉइंटर्स को Unitpr_t टाइप करना होगा और फिर बिटवाइज़ ऑपरेशंस करने होंगे।
यहाँ एक फ़ंक्शन का एक उदाहरण है जिसे मैंने XOR लिंक की गई सूची में संग्रहीत करने के लिए बिटवाइज़ एक्सक्लूसिव या 2 पॉइंटर्स करने के लिए लिखा है ताकि हम दोनों दिशाओं में एक दोहरी लिंक वाली सूची की तरह ट्रैवर्स कर सकें, लेकिन प्रत्येक नोड में 2 पॉइंटर्स को स्टोर करने के दंड के बिना। ।
template <typename T>
T* xor_ptrs(T* t1, T* t2)
{
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(t1)^reinterpret_cast<uintptr_t>(t2));
}
एक और नेक्रोमैंसर बैज होने का जोखिम उठाते हुए, मैं uintptr_t (या यहां तक कि intptr_t) के लिए एक बहुत अच्छा उपयोग जोड़ना चाहूंगा और यह परीक्षण योग्य एम्बेडेड कोड लिख रहा है। मैं ज्यादातर विभिन्न कोड और वर्तमान में टांसिलिका प्रोसेसर पर लक्षित कोड लिखता हूं। इनमें विभिन्न देशी बस चौड़ाई हैं और तनसिलिका वास्तव में अलग कोड और डेटा बसों के साथ एक हार्वर्ड वास्तुकला है जो विभिन्न चौड़ाई हो सकती है। मैं अपने बहुत से कोड के लिए एक परीक्षण संचालित विकास शैली का उपयोग करता हूं जिसका अर्थ है कि मैं सभी कोड इकाइयों के लिए इकाई परीक्षण करता हूं जो मैं लिखता हूं। वास्तविक लक्ष्य हार्डवेयर पर यूनिट परीक्षण एक परेशानी है, इसलिए मैं आमतौर पर एक इंटेल आधारित पीसी पर या तो विंडोज या लिनक्स में सब कुछ लिखता हूं जो कि काडलिंग और जीसीसी का उपयोग करता है। कहा जा रहा है, बहुत सारे एम्बेडेड कोड में बिट ट्विडलिंग और एड्रेस मैनिपुलेशन शामिल हैं। मेरी अधिकांश इंटेल मशीनें 64 बिट की हैं। इसलिए यदि आप पता हेरफेर कोड का परीक्षण करने जा रहे हैं, तो आपको गणित करने के लिए एक सामान्यीकृत ऑब्जेक्ट की आवश्यकता है। इस प्रकार uintptr_t आपको हार्डवेयर को लक्षित करने के लिए तैनात करने से पहले अपने कोड को डिबग करने का एक स्वतंत्र तरीका देता है। एक और मुद्दा कुछ मशीनों या कुछ कंपाइलरों पर मेमोरी मॉडल के लिए भी है, फ़ंक्शन पॉइंटर्स और डेटा पॉइंटर्स अलग-अलग चौड़ाई के हैं। उन मशीनों पर कंपाइलर दो वर्गों के बीच कास्टिंग की अनुमति भी नहीं दे सकता है, लेकिन uintptr_t को या तो पकड़ करने में सक्षम होना चाहिए।