c - "एक डाली के बिना सूचक से पूर्णांक/पूर्णांक से सूचक"



pointers casting (1)

नहीं, यह वैध सी नहीं है और कभी भी वैध सी नहीं है। ये उदाहरण तथाकथित मानक के उल्लंघन हैं

मानक आपको किसी पूर्णांक के लिए सूचक को प्रारंभ / असाइन करने की अनुमति नहीं देता है, न ही एक सूचक को पूर्णांक। आपको किसी कास्ट के साथ एक प्रकार का रूपांतरण मैन्युअल रूप से करने की आवश्यकता है:

int* p = (int*) 0x1234;

int i = (int)p;

यदि आप कलाकारों का उपयोग नहीं करते हैं, तो कोड मान्य सी नहीं है और आपके कंपाइलर को संदेश प्रदर्शित किए बिना कोड पास करने की अनुमति नहीं है। विशेष रूप से, यह सरल असाइनमेंट , C17 6.5.16.1 §1 के नियमों द्वारा नियंत्रित किया जाता है:

6.5.16.1 सरल कार्य

प्रतिबन्ध

निम्नलिखित में से एक धारण करेगा:

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

int* p = 0x12345678; मामले में int* p = 0x12345678; बायाँ ऑपरेन्ड एक पॉइंटर है और राइट एक अंकगणितीय प्रकार है।
int i = p; मामले में int i = p; बायाँ ऑपरेंड एक अंकगणित प्रकार है और दाईं ओर एक पॉइंटर है।
न तो इनमें से कोई भी ऊपर उल्लिखित बाधाओं के साथ फिट बैठता है।

क्यों के लिए int* p = 0; काम करता है, यह एक विशेष मामला है। बायाँ ऑपरेन्ड एक पॉइंटर है और राईट एक नेल पॉइंटर कन्टेस्टेंट है । अशक्त संकेत, अशक्त सूचक स्थिरांक और NULL मैक्रो के बीच अंतर के बारे में अधिक जानकारी ।

नोट की कुछ बातें:

  • यदि आप एक पॉइंटर को एक कच्चे पते को असाइन करते हैं, तो पॉइंटर को volatile योग्य होने की आवश्यकता होती है, यह देखते हुए कि यह एक हार्डवेयर रजिस्टर या ईईपीआरओएम / फ्लैश मेमोरी लोकेशन जैसी किसी चीज की ओर इशारा करता है, जो रन-टाइम में अपनी सामग्री को बदल सकता है।

  • सूचक को पूर्णांक में परिवर्तित करना कलाकारों के साथ काम करने की गारंटी नहीं है। मानक (C17 6.3.2.3 and5 और says6 कहता है):

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

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

    जानकारीपूर्ण पैर नोट:

    68) एक सूचक को पूर्णांक या पूर्णांक में सूचक में बदलने के लिए मानचित्रण कार्य निष्पादन पर्यावरण की संबोधित संरचना के अनुरूप होना चाहिए।

    इसके अलावा, एक पॉइंटर से पता एक int अंदर फिट होने की तुलना में बड़ा हो सकता है, जैसा कि अधिकांश 64 बिट सिस्टम के लिए होता है। इसलिए uintptr_t को <stdint.h> से उपयोग करना बेहतर है

यह प्रश्न पूर्णांक और सूचक मुद्दों के बीच सभी आरंभीकरण / असाइनमेंट के लिए एक FAQ प्रविष्टि माना जाता है।

मैं कोड लिखना चाहता हूं जहां एक सूचक एक विशिष्ट मेमोरी पते पर सेट है, उदाहरण के लिए 0x12345678 । लेकिन जब gcc संकलक के साथ इस कोड को संकलित किया जाता है, तो मुझे "initialization एक कास्टर के बिना पूर्णांक से पॉइंटर बनाता है" वारंट / लिंक:

int* p = 0x12345678;

इसी तरह, यह कोड "आरंभीकरण बिना किसी डाली के सूचक से पूर्णांक बनाता है":

int* p = ...;
int i =  p;

अगर मैं वैरिएबल डिक्लेरेशन की लाइन के बाहर भी ऐसा करता हूं, तो मैसेज एक ही है, लेकिन "इनीशियेशन" के बजाय "असाइनमेंट" कहते हैं:

p = 0x12345678; // "assignment makes pointer from integer without a cast"
i = p;          // "assignment makes integer from pointer without a cast"

अन्य लोकप्रिय संकलकों के साथ परीक्षण भी त्रुटि / चेतावनी संदेश देते हैं:

  • क्लैंग कहते हैं "सूचक रूपांतरण के लिए असंगत पूर्णांक"
  • icc का कहना है कि "टाइप int की वैल्यू का इस्तेमाल किसी प्रकार की int* की इकाई को इनिशियलाइज़ करने के लिए नहीं किया जा सकता है"
  • MSVC (सीएल) का कहना है " int* इंटिग्रेशन के स्तरों में int से भिन्न है"।

प्रश्न: क्या उपरोक्त उदाहरण सी मान्य हैं?

और एक अनुवर्ती प्रश्न:

यह कोई चेतावनी / त्रुटि नहीं देता है:

int* p = 0;

क्यों नहीं?





assignment-operator