सी भाषा में इंगित करने वाले डेटा का "प्रकार" क्या है?


30

मुझे पता है कि संकेत पते रखते हैं। मुझे पता है कि पॉइंटर्स के प्रकार "आम तौर पर" ज्ञात होते हैं जो डेटा के "प्रकार" के आधार पर वे इंगित करते हैं। लेकिन, पॉइंटर्स अभी भी वैरिएबल हैं और उनके पास मौजूद पते में डेटा "टाइप" होना चाहिए। मेरी जानकारी के अनुसार, पते हेक्साडेसिमल प्रारूप में हैं। लेकिन, मैं अभी भी नहीं जानता कि डेटा का "प्रकार" यह हेक्साडेसिमल क्या है। (ध्यान दें कि मुझे पता है कि एक हेक्साडेसिमल क्या है, लेकिन जब आप कहते हैं 10CBA20, उदाहरण के लिए, क्या यह वर्णों का स्ट्रिंग है? पूर्णांक? क्या? क्या? जब मैं पते पर पहुंचना चाहता हूं और इसे हेरफेर करना चाहता हूं .. खुद, मुझे इसके प्रकार को जानने की आवश्यकता है। " इसलिए मैं पूछ रहा हूं।)


17
संकेत चर नहीं हैं , लेकिन मूल्य हैं । वेरिएबल्स मान रखते हैं (और यदि उनका प्रकार एक सूचक प्रकार है, तो यह मान एक सूचक है, और एक मेमोरी ज़ोन का पता हो सकता है जिसमें कुछ सार्थक हो)। एक दिए गए मेमोरी ज़ोन का उपयोग विभिन्न प्रकार के विभिन्न मूल्यों को रखने के लिए किया जा सकता है।
बेसिल स्टारीनेवविच

29
"पते हेक्साडेसिमल प्रारूप में हैं" नहीं, यह सिर्फ डिबगर या लाइब्रेरी प्रारूपण बिट्स है। उसी तर्क के साथ आप कह सकते हैं कि वे बाइनरी या ऑक्टल में हैं।
usr

आप प्रारूप के बारे में पूछना बेहतर होगा , न कि प्रकार । इसलिए नीचे कुछ ऑफ-पिस्ट उत्तर ... (हालांकि किलियन स्पॉट-ऑन है)।
लाइटनेस रेस मोनिका

1
मुझे लगता है कि ओपी के प्रकार के बारे में यहां गहरा मुद्दा है । जब यह इसके नीचे आता है, तो आपके प्रोग्राम में जिन मानों में हेरफेर किया जाता है, वे स्मृति में बिट्स होते हैं। कंपाइलर टाइप करने के प्रकार प्रोग्रामर का तरीका है कि विधानसभा कोड उत्पन्न करते समय उन बिट्स का इलाज कैसे करें।
जस्टिन लार्दीनो

मुझे लगता है कि उन सभी उत्तरों के साथ इसे संपादित करने में बहुत देर हो चुकी है, लेकिन यह सवाल बेहतर होता अगर आपने हार्डवेयर और / या ऑपरेटिंग सिस्टम को प्रतिबंधित किया होता, उदाहरण के लिए "x64 लिनक्स पर"।
हाइड

जवाबों:


64

सूचक चर का प्रकार है .. सूचक।

आप जिन कार्यों को औपचारिक रूप से C में करने की अनुमति देते हैं, उनकी तुलना पूर्णांक में जोड़ने या घटाने के लिए, या इसे दूसरे बिंदुओं पर लाने के लिए (अन्य बिंदुओं, या विशेष NULL / शून्य मान से) करने के लिए होती है।

एक बार जब आप अपरिभाषित व्यवहार को स्वीकार करते हैं , तो आप देख सकते हैं कि वास्तव में मूल्य क्या है। यह आमतौर पर एक मशीन शब्द होगा, एक पूर्णांक के रूप में एक ही तरह की चीज, और आमतौर पर एक पूर्णांक प्रकार से दोषरहित रूप से डाली जा सकती है। (बहुत सारे विंडोज कोड DWORD या HANDLE टाइपडिफ्स में संकेत छिपाकर ऐसा करते हैं)।

कुछ ऐसे आर्किटेक्चर हैं जहां पॉइंटर्स सरल नहीं हैं क्योंकि मेमोरी फ्लैट नहीं है। डॉस / 8086 'पास' और 'दूर'; PIC की अलग मेमोरी और कोड स्पेस।


2
आपको दो बिंदुओं के बीच अंतर करने की भी अनुमति है p1-p2। परिणाम एक हस्ताक्षरित अभिन्न मूल्य है। विशेष रूप से,&(array[i])-&(array[j]) == i-j
MSalters

13
वास्तव में, एक अभिन्न प्रकार में रूपांतरण भी निर्दिष्ट है, विशेष रूप से intptr_tऔर uintptr_tजो सूचक मूल्यों के लिए "बड़े पर्याप्त" होने की गारंटी है।
मथिउ एम।

3
आप कार्य करने के लिए रूपांतरण पर निर्भर हो सकते हैं, लेकिन पूर्णांकों और बिंदुओं के बीच मानचित्रण कार्यान्वयन-परिभाषित है। (एकमात्र अपवाद 0 -> अशक्त है, और यहां तक ​​कि केवल निर्दिष्ट है यदि 0 एक निरंतर IIRC है।)
cHao

7
pप्रिंट करने के लिए स्पेसिफ़ायर को जोड़ने से एक शून्य पॉइंटर के मानव-पठनीय प्रतिनिधित्व को परिभाषित किया जा सकता है, यदि कार्यान्वयन सी में निर्भर व्यवहार को लागू करता है।
dmckee

6
इस उत्तर में आम तौर पर सही विचार है, लेकिन विशिष्ट दावों पर विफल रहता है। इंटीग्रल टाइप के लिए पॉइंटर को लगाना अपरिभाषित व्यवहार नहीं है, और विंडोज हैण्डल डेटा टाइप्स पॉइंटर वैल्यू नहीं हैं (वे इंटीग्रल डेटा टाइप्स में छिपे हुए पॉइंटर्स नहीं हैं, वे एरियर्स को रोकने के लिए पॉइंटर टाइप्स में छिपे हुए इंटीजर हैं)।
बेन वोइगट

44

आप चीजों को ओवरकॉम्प्लिकेट कर रहे हैं।

पते केवल पूर्णांक, अवधि हैं। आदर्श रूप से वे संदर्भित मेमोरी सेल की संख्या हैं (व्यवहार में यह सेगमेंट, वर्चुअल मेमोरी आदि के कारण अधिक जटिल हो जाता है)।

हेक्साडेसिमल सिंटैक्स एक पूर्ण कल्पना है जो केवल प्रोग्रामर की सुविधा के लिए मौजूद है। 0x1A और 26 वास्तव में एक ही प्रकार के एक ही नंबर हैं , और न ही कंप्यूटर क्या उपयोग करता है - आंतरिक रूप से, कंप्यूटर हमेशा 00011010 (बाइनरी सिग्नल की एक श्रृंखला) का उपयोग करता है।

संकलक आपको पॉइंटर्स का इलाज करने की अनुमति देता है या नहीं, क्योंकि संख्याएँ भाषा की परिभाषा पर निर्भर करती हैं - "सिस्टम प्रोग्रामिंग" भाषा परंपरागत रूप से अधिक पारदर्शी होती है कि कैसे चीजें हुड के नीचे काम करती हैं, जबकि "उच्च-स्तरीय" भाषाएं अधिक बार नंगे धातु को छिपाने की कोशिश करती हैं। प्रोग्रामर से - लेकिन यह इस तथ्य के बारे में कुछ भी नहीं बदलता है कि संकेत संख्याएं हैं, और आमतौर पर सबसे सामान्य प्रकार की संख्या (आपके प्रोसेसर आर्किटेक्चर के रूप में कई बिट्स के साथ एक)।


26
पते निश्चित रूप से पूर्णांक नहीं हैं। जैसे फ्लोटिंग-पॉइंट नंबर निश्चित रूप से सिर्फ पूर्णांक नहीं हैं।
gnasher729

8
वास्तव में। सबसे प्रसिद्ध ज्ञात प्रतिरूप इंटेल 8086 है, जहां संकेत दो पूर्णांक हैं।
MSalters

5
@Rob खंडित मेमोरी मॉडल में, एक सूचक या तो एकल मान (खंड की शुरुआत के लिए एक संबोधन; एक खंड) एक खंड, या खंड / चयनकर्ता और ऑफसेट जोड़ी के साथ हो सकता है । (मुझे लगता है कि इंटेल ने "चयनकर्ता" शब्द का इस्तेमाल किया है; मैं इसे देखने के लिए बहुत आलसी हूं।) 8086 में, इन्हें दो 16-बिट पूर्णांक के रूप में दर्शाया गया था, जो एक 20-बिट भौतिक पता बनाने के लिए संयुक्त था। (हां, आप एक ही मेमोरी सेल को कई, कई अलग-अलग तरीकों से संबोधित कर सकते हैं, यदि आप बहुत इच्छुक थे: पता = (खंड << 4 + ऑफसेट) और 0xfffff।) यह वास्तविक मोड में चलने पर सभी x86 कंपेटिबल्स के माध्यम से आगे बढ़ाया।
बजे एक सीवी

4
एक लंबी अवधि के असेंबलर प्रोग्रामर के रूप में, मैं यह पुष्टि कर सकता हूं कि कंप्यूटर की मेमोरी पूर्णांक रखने वाली मेमोरी स्थानों के अलावा और कुछ नहीं है। हालाँकि, यह है कि आप उनके साथ कैसा व्यवहार करते हैं और उन बातों पर नज़र रखते हैं जो पूर्णांक का प्रतिनिधित्व करते हैं। जैसे मेरे सिस्टम पर, दशमलव संख्या 4075876853 को x'F2F0F1F5 'के रूप में संग्रहीत किया गया है, जो EBCDIC में स्ट्रिंग' 2015 'है। दशमलव 2015 को 000007DF के रूप में संग्रहीत किया जाएगा, जबकि x'0002015C 'पैक-दशमलव प्रारूप में दशमलव 2015 का प्रतिनिधित्व करता है। एक असेंबलर प्रोग्रामर के रूप में, आपको इन पर नज़र रखनी होगी; संकलक यह एचएल भाषाओं के लिए करता है।
स्टीव इव्स

7
पतों को पूर्णांक के साथ एक-से-एक पत्राचार में रखा जा सकता है, लेकिन इसलिए कंप्यूटर पर बाकी सब कुछ हो सकता है :)
hobbs

16

एक पॉइंटर सिर्फ एक पॉइंटर है। यह कुछ और नहीं है। यह सोचने की कोशिश मत करो कि यह कुछ और है।

C, C ++ और Objective-C जैसी भाषाओं में, डेटा पॉइंटर्स में चार प्रकार के संभावित मान होते हैं:

  1. एक संकेतक एक वस्तु का पता हो सकता है।
  2. एक सूचक किसी सरणी के अंतिम तत्व को इंगित कर सकता है।
  3. एक सूचक एक शून्य सूचक हो सकता है, जिसका अर्थ है कि यह किसी भी चीज़ की ओर इशारा नहीं कर रहा है।
  4. एक सूचक का अनिश्चित मान हो सकता है, दूसरे शब्दों में यह बकवास है, और कुछ भी हो सकता है (बुरी चीजों सहित) यदि आप इसका उपयोग करने का प्रयास करते हैं।

फंक्शन पॉइंटर्स भी होते हैं, जो या तो किसी फंक्शन की पहचान करते हैं, या फिर न्यूल फंक्शन पॉइंटर्स होते हैं, या एक अनिश्चित मान होता है।

अन्य संकेत C ++ में "पॉइंटर टू मेंबर" हैं। ये निश्चित रूप से स्मृति पते नहीं हैं! इसके बजाय, वे एक वर्ग के किसी भी उदाहरण के सदस्य की पहचान करते हैं । ऑब्जेक्टिव-सी में, आपके पास चयनकर्ता होते हैं, जो "किसी दिए गए विधि के नाम और तर्क के नाम के साथ इंस्टेंस विधि के सूचक" जैसे होते हैं। एक सदस्य सूचक की तरह, यह सभी वर्गों के सभी तरीकों की पहचान करता है जब तक वे समान दिखते हैं।

आप जांच कर सकते हैं कि एक विशिष्ट संकलक पॉइंटर्स को कैसे लागू करता है, लेकिन यह एक पूरी तरह से अलग सवाल है।


4
कार्यों के लिए संकेत हैं और, सी ++ में, सदस्यों को संकेत हैं।
श्रीधाम

सदस्यों के लिए सी ++ संकेत स्मृति पते नहीं हैं? निश्चित ही वे हैं। यदि कोड की अंतिम पंक्ति स्थापित होती है, तो वर्ग के उदाहरण के सदस्य के पते के रूप में, class A { public: int num; int x; }; int A::*pmi = &A::num; A a; int n = a.*pmi;चर का pmiउपयोग नहीं किया जाएगा , तो चर का उपयोग बहुत अधिक नहीं होगा । आप इसे एक साधारण पॉइंटर में डाल सकते हैं (हालांकि कंपाइलर शायद आपको एक चेतावनी देगा) और इसे सफलतापूर्वक विघटित करना (यह साबित करना कि यह किसी अन्य पॉइंटर के लिए सिंटैक्टिक चीनी है)। numaAint
dodgethesteamroller

9

एक सूचक एक बिट पैटर्न है जो रैम में भंडारण के एक शब्द को (पढ़ने या लिखने के उद्देश्य से विशिष्ट पहचान) है। ऐतिहासिक और पारंपरिक कारणों से अपडेट की इकाई आठ बिट्स है, जिसे अंग्रेजी में "बाइट" या फ्रेंच में, बल्कि तार्किक रूप से, ऑक्टेट के रूप में जाना जाता है। यह सर्वव्यापी है लेकिन अंतर्निहित नहीं है; अन्य आकार मौजूद हैं।

अगर मुझे सही से याद है कि एक कंप्यूटर था जिसमें एक 29 बिट शब्द का इस्तेमाल किया गया था; न केवल यह दो की शक्ति है, यह भी प्रमुख है। मैंने सोचा कि यह SILLIAC था, लेकिन प्रासंगिक विकिपीडिया लेख इसका समर्थन नहीं करता है। CAN बस 29 बिट पतों का उपयोग करता है, लेकिन कन्वेंशन द्वारा नेटवर्क पतों को कार्यात्मक रूप से समान होने पर भी पॉइंटर्स के रूप में संदर्भित नहीं किया जाता है।

लोग दावा करते हैं कि संकेत पूर्णांक हैं। यह न तो आंतरिक है और न ही आवश्यक है, लेकिन अगर हम बिट पैटर्न की व्याख्या करते हैं , तो पूर्णांक के रूप में क्रमिकता की उपयोगी गुणवत्ता उभरती है, जिससे "स्ट्रिंग" और "एरे" जैसे निर्माणों के कार्यान्वयन में बहुत प्रत्यक्ष (और इसलिए छोटे हार्डवेयर पर कुशल) सक्षम होता है। सन्निहित स्मृति की धारणा क्रमिक आसन्नता पर निर्भर करती है, और सापेक्ष स्थिति संभव है; पूर्णांक तुलना और अंकगणितीय संचालन को सार्थक रूप से लागू किया जा सकता है। इस कारण से भंडारण पते के लिए शब्द आकार और ALU (पूर्णांक गणित करने वाली बात) के बीच लगभग हमेशा मजबूत संबंध है।

कभी-कभी दोनों मेल नहीं खाते। प्रारंभिक पीसी में पता बस 24 बिट चौड़ा था।


नाइटपिक, इन दिनों सामान्य ओएस में, पॉइंटर वर्चुअल मेमोरी में स्थान की पहचान करता है, और इसका भौतिक रैम शब्द से कोई सीधा संबंध नहीं है (वर्चुअल मेमोरी लोकेशन भी भौतिक रूप से मौजूद नहीं हो सकता है अगर यह ओएस द्वारा सभी जीरो होने के लिए ज्ञात मेमोरी पेज में है। )।
हाइड

@II - आपके तर्क में उस संदर्भ में योग्यता है जिसमें आपने स्पष्ट रूप से इसका इरादा किया था, लेकिन कंप्यूटर का प्रमुख रूप एम्बेडेड नियंत्रक है, जहां आभासी स्मृति जैसे चमत्कार सीमित तैनाती के साथ हाल ही में नवाचार हैं। इसके अलावा, आपने जो इंगित किया है, वह ओपी को संकेत समझने में मदद करता है। मुझे लगा कि कुछ ऐतिहासिक संदर्भ यह सब बहुत कम मनमाना बना देगा।
पीटर

मुझे नहीं पता कि रैम के बारे में बात करने से ओपी को समझने में मदद मिलेगी, क्योंकि यह सवाल विशेष रूप से है कि वास्तव में पॉइंटर्स क्या हैं। ओह, एक और नाइटपिक, पॉइंटर में परिभाषा बिंदुओं से बाइट के लिए (सुरक्षित रूप से char*उदाहरण के लिए डाली जा सकती है । मेमोरी कॉपी / तुलना के प्रयोजनों के लिए, और sizeof char==1सी मानक द्वारा परिभाषित के रूप में), शब्द नहीं (जब तक कि सीपीयू शब्द का आकार बाइट आकार के समान नहीं है)।
हाइड

मूल रूप से क्या संकेत हैं भंडारण के लिए हैश कुंजी। यह भाषा और प्लेटफ़ॉर्म अपरिवर्तनीय है।
पीटर विन

सवाल c पॉइंटर्स के बारे में है । और संकेत निश्चित रूप से हैश कुंजी नहीं हैं, क्योंकि कोई हैश तालिका नहीं है, कोई हैशिंग एल्गोरिथ्म नहीं है। वे स्वाभाविक रूप से कुछ प्रकार के मानचित्र / शब्दकोश कुंजी हैं ("मानचित्र" की पर्याप्त व्यापक परिभाषा के लिए), लेकिन हैश कुंजी नहीं ।
हाइड

6

मूल रूप से हर आधुनिक कंप्यूटर एक बिट-पुश मशीन है। आमतौर पर यह डेटा के समूहों में बिट्स को चारों ओर धकेलता है, जिसे बाइट्स, वर्ड्स, डीआईडीएस या क्यूवर्ड कहा जाता है।

एक बाइट में 8 बिट्स होते हैं, एक शब्द 2 बाइट्स (या 16 बिट्स), एक डॉर्ड 2 शब्द (या 32 बिट्स) और एक क्वॉर्ड 2 डीआईडीएस (या 64 बिट्स)। ये बिट्स की व्यवस्था करने का एकमात्र तरीका नहीं हैं। 128 बिट और 256 बिट हेरफेर भी होता है, अक्सर SIMD के निर्देशों में।

विधानसभा निर्देश रजिस्टरों पर काम करते हैं और मेमोरी पते आमतौर पर उपरोक्त रूपों में से एक में काम करते हैं।

ALU (अंकगणितीय तर्क इकाइयाँ) बिट्स के ऐसे बंडलों पर काम करती हैं जैसे कि वे पूर्णांक (आमतौर पर दो के पूरक प्रारूप) का प्रतिनिधित्व करते हैं, और FPUs जैसे कि वे जहां फ्लोटिंग पॉइंट वैल्यू (आमतौर पर IEEE 754-स्टाइल floatऔर double)। अन्य भाग ऐसे कार्य करेंगे जैसे कि वे किसी प्रारूप, वर्ण, तालिका प्रविष्टियाँ, CPU निर्देश, या पते का बंडल डेटा हैं।

एक सामान्य 64 बिट कंप्यूटर पर, 8 बाइट्स (64 बिट्स) के बंडल पते होते हैं। हम इन पतों को एक हेक्स प्रारूप (जैसे 0xabcd1234cdef5678) में पारंपरिक रूप से प्रदर्शित करते हैं , लेकिन यह मनुष्य के लिए बिट पैटर्न को पढ़ने का एक आसान तरीका है। प्रत्येक बाइट (8 बिट) को दो हेक्स वर्णों के रूप में लिखा जाता है (प्रत्येक हेक्स चरित्र - 0 से एफ - 4 बिट्स का प्रतिनिधित्व करता है)।

वास्तव में क्या चल रहा है (वास्तव में कुछ स्तर के लिए) यह है कि बिट्स हैं, आमतौर पर एक रजिस्टर में संग्रहीत या मेमोरी बैंक में आसन्न स्थानों में संग्रहीत किया जाता है, और हम उन्हें किसी अन्य मानव का वर्णन करने का प्रयास कर रहे हैं।

एक पॉइंटर के बाद मेमोरी कंट्रोलर से हमें उस स्थान पर कुछ डेटा देने के लिए कहा जाता है। आप आम तौर पर एक निश्चित स्थान पर एक निश्चित संख्या में बाइट्स के लिए मेमोरी कंट्रोलर से पूछेंगे (अच्छी तरह से, स्थानों की एक सीमा, आमतौर पर सन्निहित), और यह विभिन्न तंत्रों के माध्यम से दिया जाता है जो मुझे नहीं मिलेगा।

कोड आमतौर पर डेटा को लाने के लिए एक गंतव्य निर्दिष्ट करता है - एक रजिस्टर, एक अन्य मेमोरी एड्रेस आदि - और आमतौर पर एक पूर्णांक, या इसके विपरीत की उम्मीद में फ्लोटिंग पॉइंट डेटा को एक रजिस्टर में लोड करना एक बुरा विचार है।

C / C ++ में डेटा का प्रकार कुछ ऐसा है जिसे कंपाइलर ट्रैक करता है, और यह बदलता है कि कोड क्या उत्पन्न होता है। आमतौर पर डेटा में कुछ भी आंतरिक नहीं होता है जो इसे वास्तव में किसी एक प्रकार का बनाता है । बिट्स का एक संग्रह (बाइट्स में व्यवस्थित) जो कोड द्वारा एक पूर्णांक-जैसे तरीके (या एक फ्लोट-जैसे तरीके, या एक पते की तरह) में हेरफेर किया जाता है।

इसके अपवाद हैं। ऐसे आर्किटेक्चर हैं जहां कुछ चीजें अलग तरह की होती हैं। सबसे सामान्य उदाहरण संरक्षित निष्पादन पृष्ठ हैं - सीपीयू को बताते हुए निर्देश कि बिट्स क्या हैं, चलाने के समय (मेमोरी) पृष्ठों को निष्पादित करने के लिए कोड विशेष रूप से चिह्नित हैं, संशोधित नहीं किया जा सकता है, और आप उन पृष्ठों को निष्पादित नहीं कर सकते हैं जो चिह्नित नहीं हैं। निष्पादन पृष्ठों के रूप में।

केवल डेटा को भी पढ़ा जाता है (कभी-कभी ROM में संग्रहीत होता है जिसे भौतिक रूप से नहीं लिखा जा सकता है!), संरेखण मुद्दे (कुछ प्रोसेसर doubleमेमोरी से s लोड नहीं कर सकते हैं जब तक कि वे विशेष तरीकों से संरेखित न हों, या SIMD निर्देश जिसमें कुछ संरेखण की आवश्यकता होती है), और असंख्य अन्य वास्तुकला quirks।

यहां तक ​​कि विस्तार का उपरोक्त स्तर झूठ है। कंप्यूटर बिट्स के आसपास "वास्तव में" नहीं हैं, वे वास्तव में वोल्टेज और वर्तमान के आसपास जोर दे रहे हैं। ये वोल्टेज और करंट कभी-कभी वे नहीं करते हैं जो वे बिट्स के अमूर्त स्तर पर करने के लिए "माना" जाते हैं। चिप्स को ऐसी अधिकांश त्रुटियों का पता लगाने और उच्च स्तरीय अमूर्तता के बिना उन्हें ठीक करने के लिए डिज़ाइन किया गया है ताकि इसके बारे में पता चल सके।

वह भी झूठ है।

अमूर्तता का प्रत्येक स्तर नीचे एक को छुपाता है, और आपको प्रिंट आउट के क्रम में फेनमैन आरेखों को ध्यान में रखे बिना समस्याओं को हल करने के बारे में सोचने देता है "Hello World"

तो ईमानदारी के पर्याप्त स्तर पर, कंप्यूटर बिट्स को धक्का देते हैं, और उन बिट्स को अर्थ दिया जाता है कि उनका उपयोग कैसे किया जाता है।


3

लोगों ने एक बड़ा सौदा किया है कि क्या संकेत पूर्णांक हैं या नहीं। वास्तव में इन सवालों के जवाब हैं। हालांकि, आपको विशिष्टताओं की भूमि में कदम रखना होगा, जो दिल के बेहोश होने के लिए नहीं है। हम सी विनिर्देश, आईएसओ / आईईसी 9899: TC2 पर एक नज़र डालने जा रहे हैं

6.3.2.3 अंक

  1. पूर्णांक को किसी भी सूचक प्रकार में परिवर्तित किया जा सकता है। पहले से निर्दिष्ट के अलावा, परिणाम कार्यान्वयन-परिभाषित है, सही ढंग से गठबंधन नहीं किया जा सकता है, संदर्भित प्रकार की इकाई को इंगित नहीं कर सकता है, और एक जाल प्रतिनिधित्व हो सकता है।

  2. किसी भी सूचक प्रकार को पूर्णांक प्रकार में परिवर्तित किया जा सकता है। पहले से निर्दिष्ट के अलावा, परिणाम कार्यान्वयन-परिभाषित है। यदि परिणाम पूर्णांक प्रकार में प्रदर्शित नहीं किया जा सकता है, तो व्यवहार अपरिभाषित है। परिणाम किसी भी पूर्णांक प्रकार के मूल्यों की सीमा में नहीं होना चाहिए।

अब इसके लिए, आपको कुछ सामान्य विशेष शर्तों को जानना होगा। "कार्यान्वयन परिभाषित" का अर्थ है कि हर एक संकलक को इसे अलग तरीके से परिभाषित करने की अनुमति है। वास्तव में, एक कंपाइलर भी आपके कंपाइलर सेटिंग्स के आधार पर इसे अलग-अलग तरीके से परिभाषित कर सकता है। अपरिभाषित व्यवहार का अर्थ है संकलक को बिल्कुल कुछ भी करने की अनुमति है, एक संकलन समय त्रुटि देने से लेकर अनपेक्षित व्यवहार तक, पूरी तरह से काम करने के लिए।

इससे हम देख सकते हैं कि अंतर्निहित भंडारण प्रपत्र निर्दिष्ट नहीं है, इसके अलावा एक पूर्णांक प्रकार में रूपांतरण हो सकता है। अब सच कहा जाए, सूरज के नीचे लगभग हर कंपाइलर पूर्णांक के पते के रूप में हुड के नीचे पॉइंटर्स का प्रतिनिधित्व करता है (कुछ विशेष मामलों के साथ जहां इसे सिर्फ 1 के बजाय 2 पूर्णांक के रूप में दर्शाया जा सकता है), लेकिन विनिर्देश बिल्कुल कुछ भी अनुमति देता है, जैसे कि प्रतिनिधित्व करना 10 चरित्र स्ट्रिंग के रूप में पते!

यदि हम C से बाहर तेजी से आगे बढ़ते हैं और C ++ युक्ति को देखते हैं, तो हमें थोड़ी और स्पष्टता मिलती है reinterpret_cast, लेकिन यह एक अलग भाषा है, इसलिए आपके लिए इसका मूल्य भिन्न हो सकता है:

ISO / IEC N337: C ++ 11 ड्राफ्ट विनिर्देश (मेरे पास केवल ड्राफ्ट है)

5.2.10 पुनर्व्याख्या डाली

  1. एक सूचक को स्पष्ट रूप से किसी भी अभिन्न प्रकार में परिवर्तित किया जा सकता है जो इसे धारण करने के लिए पर्याप्त हो। मैपिंग फ़ंक्शन कार्यान्वयन-परिभाषित है। [नोट: यह उन लोगों के लिए अनिश्चित है, जो अंतर्निहित मशीन की संरचना को जानते हैं। -एंड नोट] प्रकार std का मान :: nullptr_t को अभिन्न प्रकार में बदला जा सकता है; रूपांतरण का एक ही अर्थ और वैधता है जो अभिन्न प्रकार के (शून्य *) 0 के रूपांतरण के रूप में है। [नोट: किसी भी प्रकार के मान को std :: nullptr_t में बदलने के लिए एक रीइंटरप्रिट_का उपयोग नहीं किया जा सकता है। ध्यान दें]

  2. अभिन्न प्रकार या गणना प्रकार का मान स्पष्ट रूप से सूचक में परिवर्तित हो सकता है। एक पॉइंटर पर्याप्त आकार के पूर्णांक में परिवर्तित हो जाता है (यदि कार्यान्वयन पर ऐसा कोई भी मौजूद है) और वापस उसी पॉइंटर प्रकार में अपना मूल मान होगा; संकेत और पूर्णांक के बीच मैपिंग अन्यथा कार्यान्वयन-परिभाषित हैं। [नोट: ३. 3.7.४.३ में वर्णित के अलावा, इस तरह के रूपांतरण का परिणाम एक सुरक्षित रूप से व्युत्पन्न पॉइंटर मूल्य नहीं होगा। ध्यान दें]

जैसा कि आप यहां देख सकते हैं, इसकी बेल्ट के तहत कुछ और वर्षों के साथ, C ++ ने पाया कि यह मान लेना सुरक्षित था कि पूर्णांक के लिए एक मैपिंग मौजूद है, इसलिए अब अपरिभाषित व्यवहार की बात नहीं है (हालांकि 4 और 4 के बीच एक दिलचस्प विरोधाभास है) 5 "यदि कार्यान्वयन पर ऐसा कोई मौजूद है"


अब इससे आपको क्या लेना देना?

  • पॉइंटर्स का सटीक प्रतिनिधित्व कार्यान्वयन परिभाषित है। (वास्तव में, इसे गड़बड़ करने के लिए, कुछ छोटे एम्बेडेड कंप्यूटर अशक्त सूचक का प्रतिनिधित्व करते हैं, (शून्य ) 0, पते 255 के रूप में कुछ पते का समर्थन करने के लिए अलियासिंग ट्रिक्स जो वे उपयोग करते हैं) *
  • यदि आपको मेमोरी में पॉइंटर्स के प्रतिनिधित्व के बारे में पूछना है, तो आप शायद अपने प्रोग्रामिंग करियर में उस बिंदु पर नहीं हैं जहाँ आप उनके साथ फ़िदा होना चाहते हैं।

सबसे अच्छी शर्त: कास्टिंग एक (चार *)। C और C ++ विनिर्देशन नियमों से भरे हुए हैं जो एरेज़ और स्ट्रक्चर्स की पैकिंग को निर्दिष्ट करते हैं, और दोनों हमेशा किसी भी पॉइंटर की ढलाई को चार * की अनुमति देते हैं। char हमेशा 1 बाइट होता है (C में गारंटी नहीं है, लेकिन C ++ 11 द्वारा यह भाषा का अनिवार्य हिस्सा बन गया है, इसलिए यह मान लेना अपेक्षाकृत सुरक्षित है कि यह 1 बाइट है)। यह आपको बाइट-बाय-बाइट स्तर पर कुछ पॉइंटर अंकगणित करने की अनुमति देता है, वास्तव में पॉइंटर्स के कार्यान्वयन के विशिष्ट प्रतिनिधित्व को जानने की आवश्यकता के बिना।


क्या आप आवश्यक रूप से एक फंक्शन पॉइंटर को कास्ट कर सकते हैं char *? मैं एक काल्पनिक मशीन के बारे में सोच रहा हूं जिसमें कोड और डेटा के लिए अलग-अलग पता स्थान हैं।
फिलिप केंडल

@PhilipKendall अच्छी बात है। मैंने कल्पना के उस हिस्से को शामिल नहीं किया था, लेकिन फ़ंक्शन पॉइंटर्स को विनिर्देश में डेटा पॉइंटर्स की तुलना में पूरी तरह से अलग चीज के रूप में माना जाता है क्योंकि आप जिस मुद्दे को उठाते हैं। सदस्य बिंदुओं को भी अलग तरह से व्यवहार किया जाता है (लेकिन वे भी बहुत अलग तरह से कार्य करते हैं)
कॉर्ट अमोन - 15-12 पर मोनिका

charC में हमेशा A 1 बाइट होता है। C मानक से कोटेशन: "साइज़ोफ़ ऑपरेटर अपने ऑपरेंड के आकार (बाइट्स में) का उत्पादन करता है" और "जब साइज़ोफ़ को एक ऑपरेंड पर लागू किया जाता है जिसमें टाइप चार, अहस्ताक्षरित चार या हस्ताक्षरित चार होते हैं। (या उसके योग्य संस्करण) परिणाम १ है। " शायद आप सोच रहे हैं कि एक बाइट 8 बिट लंबा है। जरूरी नहीं कि ऐसा ही हो। मानक के अनुरूप होने के लिए, एक बाइट में कम से कम 8 बिट्स होने चाहिए।
डेविड हैमेन

युक्ति सूचक और पूर्णांक प्रकारों के बीच कनवर्ट करने का वर्णन करती है । यह हमेशा ध्यान में रखा जाना चाहिए कि प्रकारों के बीच एक "रूपांतरण" प्रकार की समानता नहीं करता है, न ही यह भी कि स्मृति में दो प्रकारों के एक द्विआधारी प्रतिनिधित्व में एक ही बिट पैटर्न होगा। (ASCII को EBCDIC में "कन्वर्ट" किया जा सकता है। बिग-एंडियन को "
एंडीज

1

अधिकांश आर्किटेक्चर पर, एक पॉइंटर का प्रकार मशीन कोड में अनुवादित होने के बाद बंद हो जाता है (शायद "फैट पॉइंटर्स" को छोड़कर)। इसलिए, एक पॉइंटर को intएक पॉइंटर से ए double, कम से कम अपने आप में एक अप्रभेद्य होगा । *

[*] हालांकि, आप अभी भी उस प्रकार के ऑपरेशनों के आधार पर अनुमान लगा सकते हैं जो आप उस पर लागू करते हैं।


1

C और C ++ के बारे में समझने के लिए एक महत्वपूर्ण बात यह है कि वास्तव में प्रकार क्या हैं। वे सभी वास्तव में कंपाइलर को संकेत देते हैं कि बिट्स / बाइट्स के सेट की व्याख्या कैसे करें। निम्नलिखित कोड से शुरू करें:

int var = -1337;

वास्तुकला के आधार पर, एक पूर्णांक को आमतौर पर उस मान को संग्रहीत करने के लिए 32 बिट्स की जगह दी जाती है। इसका मतलब है कि मेमोरी में वह स्थान जहाँ var संग्रहित है, "11111111 11111111 11111010 11000111" या हेक्स "0xFFFFFAC7" जैसा कुछ दिखाई देगा। बस। वह सब उस स्थान पर संग्रहीत है। सभी प्रकार के कंपाइलर को उस जानकारी की व्याख्या करने का तरीका बताया जाता है। संकेत अलग नहीं हैं। अगर मैं ऐसा कुछ करता हूं:

int* var_ptr = &var;   //the ampersand is telling C "get the address where var's value is located"

तब कंपाइलर को var का स्थान मिलेगा, और फिर उस पते को उसी तरह से स्टोर करेंगे जैसे कि पहला कोड स्निपेट वैल्यू -1337 बचाता है। उन्हें कैसे संग्रहीत किया जाता है, इसमें कोई अंतर नहीं है, बस उनका उपयोग कैसे किया जाता है। इससे कोई फर्क नहीं पड़ता कि मैंने var_ptr को सूचक को int में बनाया है। यदि आप चाहते थे, तो आप कर सकते थे।

unsigned int var2 = *(unsigned int*)var_ptr;

यह var के उपरोक्त हेक्स मान (0xFFFFFAC7) को उस स्थान पर कॉपी करेगा जो var2 के मान को संग्रहीत करता है। यदि हम तब var2 का उपयोग करते थे, तो हम पाएंगे कि मान 4294965959 होगा। var2 में बाइट्स var के समान होते हैं, लेकिन संख्यात्मक मान भिन्न होता है। कंपाइलर ने उनकी अलग तरह से व्याख्या की क्योंकि हमने यह बताया कि वे बिट्स एक अहस्ताक्षरित लंबे का प्रतिनिधित्व करते हैं। आप पॉइंटर वैल्यू के लिए भी ऐसा कर सकते हैं।

unsigned int var3 = (unsigned int)var_ptr;

आप इस उदाहरण में एक अहस्ताक्षरित int के रूप में var के पते का प्रतिनिधित्व करने वाले मान की व्याख्या करना चाहेंगे।

उम्मीद है कि यह आपके लिए चीजों को स्पष्ट करता है और आपको एक बेहतर अंतर्दृष्टि देता है कि सी कैसे काम करता है। कृपया ध्यान दें कि आप वास्तविक उत्पादन कोड में नीचे दी गई दो पंक्तियों में मेरे द्वारा किए गए किसी भी पागल सामान को नहीं कर सकते। वह सिर्फ प्रदर्शन के लिए था।


1

पूर्णांक।

कंप्यूटर में एड्रेस स्पेस को क्रमिक रूप से गिना जाता है, 0 से शुरू होता है, और 1. से वृद्धि होती है। इसलिए एक पॉइंटर एक पूर्णांक संख्या धारण करेगा जो एड्रेस स्पेस में एक पते से मेल खाती है।


1

प्रकार गठबंधन।

विशेष रूप से, कुछ प्रकार गठबंधन करते हैं, लगभग जैसे कि वे प्लेसहोल्डर्स के साथ पैरामीटर किए गए थे। ऐरे और पॉइंटर प्रकार इस प्रकार हैं; उनके पास एक ऐसा प्लेसहोल्डर है, जो क्रमशः एरे के तत्व का प्रकार है या जिस चीज़ को इंगित किया जा रहा है। फ़ंक्शन प्रकार भी इस तरह हैं; उनके पास मापदंडों के लिए कई प्लेसहोल्डर हो सकते हैं, और वापसी प्रकार के लिए एक प्लेसहोल्डर हो सकता है।

एक चर जिसे पॉइंटर रखने के लिए घोषित किया गया है, में "पॉइंटर टू चार" टाइप है। एक वैरिएबल जिसे इंट्री करने के लिए पॉइंटर रखने के लिए एक पॉइंटर को "पॉइंटर टू पाइंटर टू इंट" टाइप किया गया है।

एक "मान" सूचक के लिए "सूचक को int" टाइप करने के लिए एक dereference ऑपरेशन द्वारा "सूचक को int" में बदला जा सकता है। तो, प्रकार की धारणा केवल शब्द नहीं है, बल्कि एक गणितीय रूप से महत्वपूर्ण निर्माण है, जो यह निर्धारित करता है कि हम किस प्रकार के मूल्यों के साथ कर सकते हैं (जैसे कि डीरेफेरेंस, या पैरामीटर के रूप में पास या वेरिएबल को असाइन करें; यह आकार (बाइट काउंट) भी निर्धारित करता है; अनुक्रमण, अंकगणित, और वेतन वृद्धि / वृद्धि संचालन)।

PS यदि आप प्रकारों में गहराई से जाना चाहते हैं, तो इस ब्लॉग को आज़माएँ: http://www.goodmath.org/blog/2015/05/13/expressions-and-arity-part-1/

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.