2008-10-20 15 views
26

मैं अक्सर, वस्तुओं const के लिए इतना की तरह ...क्या उपयोग स्थिरांक संकेत (के रूप में संकेत करने के लिए विरोध वस्तुओं const करने के लिए) कर रहे हैं?

const int *p; 

बस इसका मतलब है कि आप पूर्णांक कि pp के माध्यम से की ओर इंगित करता है बदल नहीं सकते संकेत का उपयोग किया है। लेकिन मैं यह भी स्थिरांक संकेत के संदर्भ में देखा है, इस तरह की घोषणा की ...

int* const p; 

मैं इसे समझते हैं, इसका मतलब है कि सूचक चर ही स्थिर है के रूप में - आप पूर्णांक इसे कहते हैं बदल सकते हैं पूरे दिन, लेकिन आप इसे किसी और चीज पर नहीं बना सकते हैं।

कि क्या संभावित उपयोग के लिए होता है?

उत्तर

25

जब आप एम्बेडेड सिस्टम, या विशेष प्रयोजन के कार्यक्रमों है कि एक ही स्मृति में (मल्टी प्रोसेसर मेमोरी साझा करने अनुप्रयोगों) तो आप लगातार संकेत की जरूरत का उल्लेख करने की आवश्यकता के लिए सी कार्यक्रमों को डिजाइन कर रहे हैं।

उदाहरण के लिए, मेरे पास 32 bit MIPs processor है जिसमें little LCD संलग्न है। मुझे अपने एलसीडी डेटा को स्मृति में एक विशिष्ट बंदरगाह में लिखना है, जिसे एलसीडी नियंत्रक को भेजा जाता है।

मैं उस नंबर #define सकता है, लेकिन फिर मैं भी एक सूचक के रूप में यह कास्ट करने के लिए है, और सी संकलक के रूप में कई विकल्प जब मैं ऐसा नहीं है।

आगे, मुझे अस्थिर होने की आवश्यकता हो सकती है, जिसे भी कास्ट किया जा सकता है, लेकिन प्रदान किए गए वाक्यविन्यास का उपयोग करना आसान और स्पष्ट है - एक अस्थिर स्मृति स्थान के लिए एक कॉन्स्ट पॉइंटर।

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

-Adam

+3

माइनर नाइटपिक: मेमोरी मैप किए गए डिवाइसों के लिए आप निश्चित रूप से ('शायद' नहीं) आइटम को अस्थिर के रूप में चिह्नित करने की आवश्यकता है - अन्यथा आप यह सुनिश्चित नहीं कर पाएंगे कि संकलक वास्तव में पढ़ने या लिखने के ऑपरेशन को छोड़ देगा या नहीं। –

+0

आपको 'अस्थिर' की आवश्यकता हो सकती है अस्थिर सही है। आप डिवाइस के आधार पर 'बाधा()' और अन्य अर्थशास्त्र का उपयोग कर सकते हैं। यह सच है कि आपको मूल्यों को ध्यान से संभालने की आवश्यकता है। आईई, कैश/नो-कैश, अवरोध, आदि। यह डिवाइस के प्रकार पर निर्भर करता है और ** अस्थिर ** हमेशा सबसे अच्छा विकल्प नहीं है। –

+0

@ माइकलबुर: मैं आपसे सहमत हूं कि 'अस्थिर' निश्चित रूप से वहां होना चाहिए; दूसरी तरफ, कई कंपाइलर विक्रेताओं के हेडर परेशान नहीं लगते हैं - एक तथ्य जो कुछ हद तक परेशान हो सकता है (भले ही कंपलर आमतौर पर सही काम करते हैं, फिर भी वे एक रजिस्टर पढ़ने के प्रयासों को अनदेखा कर सकते हैं लेकिन कुछ भी नहीं कर सकते परिणाम)। – supercat

3

एक "स्थिरांक पूर्णांक" के रूप में एक ही ... संकलक जानता है इसे बदलने के लिए नहीं जा रहा है, यह अनुकूलन पर आधारित है कि मान्यताओं हो सकता है।

struct MyClass 
{ 
    char* const ptr; 
    MyClass(char* str) :ptr(str) {} 

    void SomeFunc(MyOtherClass moc) 
    { 
     for(int i=0; i < 100; ++i) 
     { 
       printf("%c", ptr[i]); 
       moc.SomeOtherFunc(this); 
     } 
    } 
} 

अब, संकलक कि पाश अनुकूलन करने के लिए काफ़ी कर सकता है --- बशर्ते वह जानता है कि SomeOtherFunc() ptr का मूल्य नहीं बदलता है। कॉन्स के साथ, संकलक जानता है कि, और धारणाएं कर सकते हैं। इसके बिना, संकलक को यह मानना ​​है कि SomeOtherFunc पीआरटी बदल जाएगा।

+0

कुछ नहीं होगा अन्यथाFunc को संकलन के लिए एक कॉन्स्ट सूचक तर्क के साथ घोषित किया जाना चाहिए? और यह भी नहीं होगा कि संकलक कैसे जानता होगा कि SomeOtherFunc सूचक को नहीं बदलेगा? तो स्थानीय सूचक को कॉन्स के रूप में घोषित करने में मदद नहीं मिलती है। –

+0

एंड्रयू: मुझे लगता है कि आप इस –

+0

@Andrew: संख्या के साथ भ्रमित पीआरआर हैं।SomeOtherFunc को MyClass ऑब्जेक्ट के किसी अन्य भाग को बदलने की पूरी तरह से अनुमति है। –

7
एक और उदाहरण

: यदि आप जानते हैं, जहां यह प्रारंभ किया गया था, तो आप भविष्य शून्य चेकों से बच सकते हैं। कंपाइलर आपको गारंटी देता है कि सूचक कभी नहीं बदला (NULL) ...

+1

सी में सी ++ में, आपके विशेष मामले (यानी गैर-नल पॉइंटर्स) में, आप इसके बजाय संदर्भों का उपयोग करते हैं। – paercebal

2

मैंने कुछ ओएलई कोड देखा है जहां आप कोड के बाहर से एक वस्तु पारित कर चुके थे और इसके साथ काम करने के लिए, आपको विशिष्ट स्मृति तक पहुंचना पड़ा कहते हैं कि इसमें पारित कर दिया। तो हम है कि कार्यों हमेशा मूल्यों चालाकी से OLE इंटरफेस के माध्यम से आया था सुनिश्चित करने के लिए स्थिरांक संकेत इस्तेमाल किया।

5

किसी भी गैर स्थिरांक सी ++ सदस्य समारोह में, this सूचक प्रकार C * const, जहां C वर्ग प्रकार है की है - आप क्या यह (यानी अपने सदस्यों) को इंगित करता है बदल सकते हैं, लेकिन आप करने के लिए इसे बदल नहीं सकता C के एक अलग उदाहरण को इंगित करें।const सदस्य फ़ंक्शंस के लिए, this टाइप const C * const है। volatile और const volatile सदस्य फ़ंक्शंस भी हैं, जिनके लिए this में volatile क्वालीफायर भी है।

3

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

'यह' एक हार्डकोडेड स्थिर सूचक है।

26

यह आपको सूचक को बदलने से बचाने की अनुमति देता है। इसका मतलब है आप उदाहरण के लिए मान्यताओं आप सूचक कभी नहीं बदलने पर या अनजाने में संशोधन से आधार पर, की रक्षा कर सकते हैं:

int* const p = &i; 

... 

p++;  /* Compiler error, oops you meant */ 
(*p)++; /* Increment the number */ 
+1

मैंने पहले कभी नहीं देखा है और मैं मानता हूं कि यह एक बहुत ही उपयोगी चाल है। – Rob

+1

यह एक चाल नहीं है :)। मैं फ़ंक्शन तर्कों के साथ जहां संभव हो वहां कांस्ट का उपयोग करने की कोशिश करता हूं ताकि यह स्पष्ट हो कि फ़ंक्शन स्ट्रिंग या संरचना को पारित नहीं करेगा। –

+0

भ्रमित करने वाली बात यह है कि कॉन्स अक्सर घोषणा में दो बार प्रकट होता है, और यह वास्तव में हो सकता है कुछ अलग पदों। आम तौर पर यह 'const uint8 * const value' जैसे कुछ के रूप में दिखाई दे सकता है। यह घोषित करता है कि पॉइंटर और मान जो इंगित करता है वह संशोधित नहीं है (लेकिन अगर जाली हो सकती है)। –

-2

हमेशा एक पूर्णांक के रूप में एक सूचक के बारे में सोच। इसका मतलब है कि

object* var; 

वास्तव में

रूप
int var; 

हां, तो एक स्थिरांक सूचक का अर्थ है कि के बारे में सोचा जा सकता है:

const object* var; 

const int var; 

और इसलिए यू हो जाता है पता नहीं बदल सकता है वें ई पॉइंटर अंक भी, और यह सब कुछ है। डेटा परिवर्तन को रोकने के लिए, आपको इसे एक कॉन्स्ट ऑब्जेक्ट में पॉइंटर बनाना होगा।

+0

पॉइंटर्स ** ** ** int की कई तरीकों से नहीं हैं। साथ ही, सवाल को स्पष्ट रूप से _'const' pointers_ के रूप में वर्णित किया गया है, _pointers 'const' objects_ पर नहीं। लेकिन आप उन्हें वैसे भी गलत तरीके से मिला है। –

1

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

मेरे पास निश्चित रूप से इस झुकाव का बैक अप लेने के लिए कोई डेटा नहीं है, लेकिन मैं अभी भी शर्त लगाऊंगा।

+0

मैं इसे अनुकूलन के लिए बहुत उपयोग करता हूं। – DavidG

+0

@ डेविड जी, ऑप्टिमाइज़ेशन के लिए 'सटीक' कैसे मायने रखता है? कोई भी चालाक संकलक यह निर्धारित कर सकता है कि आप एक चर को संशोधित करते हैं या अनुकूलित करते हैं, अगर यह उस पर आधारित हो, चाहे आप _said_ करेंगे या नहीं। –

+0

जब मैंने इस टिप्पणी को लिखा था तो 2008 में यह कुछ डिवाइसों पर वापस आया था ... लेकिन तब से दुनिया बहुत बदल गई है, और अब कंपेलरों ने बहुत सुधार किया है। – DavidG

5

एक उपयोग निम्न-स्तर (डिवाइस ड्राइवर या एम्बेडेड) कोड में है जहां आपको हार्डवेयर पिन जैसे इनपुट/आउटपुट डिवाइस पर मैप किए गए किसी विशिष्ट पते का संदर्भ देने की आवश्यकता होती है। कुछ भाषाएं आपको विशिष्ट पते पर चर जोड़ने की अनुमति देती हैं (उदा। एडा में use at है)। सी में ऐसा करने का सबसे बेवकूफ तरीका निरंतर सूचक घोषित करना है। ध्यान दें कि ऐसे उपयोगों में volatile क्वालीफायर होना चाहिए।

अन्य बार यह केवल रक्षात्मक कोडिंग है। यदि आपके पास कोई सूचक है कि नहीं होना चाहिए तो इसे घोषित करना बुद्धिमानी है कि यह परिवर्तन नहीं कर सकता है। यह कंपाइलर (और लिंट टूल्स) को संशोधित करने के गलत प्रयासों का पता लगाने की अनुमति देगा।

0

प्रकार * और स्थिरांक प्रकार * प्रकार के रूप में खुद की Think। फिर, आप देख सकते हैं कि आप उन प्रकारों का एक आधार क्यों लेना चाहते हैं।

+0

हाँ, और वह प्रकार मूल रूप से एक int है। – DavidG

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