चर के लिए C में कीवर्ड का उपयोग कब और किन उद्देश्यों के लिए किया जाना चाहिए?


58

जबकि हो रही मेरी कोड यहाँ की समीक्षा की का उपयोग कर के मुद्दे constकीवर्ड आया। मैं समझता हूं कि इसका उपयोग चर पर केवल-पढ़ने के व्यवहार को लागू करने के लिए किया जाता है।

मैं असमंजस में हूँ कि विभिन्न परिस्थितियाँ क्या हैं जब यह उपयोगी हो सकती हैं।

  • क्या इसे फ़ंक्शन प्रोटोटाइप में स्पष्टता के लिए उपयोग किया जाना चाहिए?
  • क्या इसे कोड विकास के दौरान सुरक्षा उपाय के रूप में उपयोग किया जाना चाहिए?
  • क्या रन-टाइम स्थिरांक घोषित करने के लिए विभिन्न कार्यों के दायरे में इसका उपयोग किया जाना चाहिए?
  • क्या इसका इस्तेमाल बिल्कुल किया जाना चाहिए?

ये सवाल सिर्फ उस भ्रम का उदाहरण हैं जिसका मैं सामना कर रहा हूं। सामान्य भ्रम है

  • constC प्रोग्रामिंग में कीवर्ड कब इस्तेमाल किया जाना चाहिए ?
  • C में इस कीवर्ड का उपयोग करके विभिन्न प्रकार के लाभ प्राप्त किए जा सकते हैं?
  • क्या constकीवर्ड का उपयोग करने का कोई विचार है ?


यह बताया गया है कि मेरे प्रश्न के विस्तार में इन सभी सवालों के कारण यह प्रश्न बहुत व्यापक हो सकता है। मैं सिर्फ यह स्पष्ट करना चाहता था कि ये प्रश्न मुख्य प्रश्न के बारे में भ्रम को स्पष्ट करने के लिए हैं।

चर के लिए C में कीवर्ड का उपयोग कब और किन उद्देश्यों के लिए किया जाना चाहिए?

इसे भी रीफ्रैश किया जा सकता है

constउसी के पेशेवरों और विपक्षों के साथ C` में कीवर्ड का उचित उपयोग ।


मतदान करने वालों के लिए कृपया यह बताएं कि यह किस श्रेणी में नहीं आता है Specific issues with software development। मैं काफी विशिष्ट हो रहा हूं।
असीम बंसल

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

1
@RobertHarvey ये सारे सवाल सिर्फ मेरी उलझन को समझाने के लिए हैं। मेरा एकमात्र प्रश्न इस प्रश्न का शीर्षक है। इसका एक अच्छा जवाब इन सभी संबंधित सवालों को कवर करेगा। तो यह एक रहता है specific issueconstउसी के पेशेवरों और विपक्षों के साथ C` में कीवर्ड का उचित उपयोग ।
असीम बंसल

@RobertHarvey क्या अब बेहतर है?
असीम बंसल

जवाबों:


64

कोड की समीक्षा करते समय, मैं निम्नलिखित नियम लागू करता हूं:

  • हमेशा constसंदर्भ द्वारा पारित फ़ंक्शन मापदंडों के लिए उपयोग करें जहां फ़ंक्शन इंगित किए गए डेटा को संशोधित (या मुफ्त) नहीं करता है।

    int find(const int *data, size_t size, int value);
  • हमेशा constस्थिरांक के लिए उपयोग करें जो अन्यथा # डिफाइन या एनम का उपयोग करके परिभाषित किया जा सकता है। कंपाइलर डेटा को रीड-ओनली मेमोरी (ROM) में परिणाम के रूप में ढूँढ सकता है (हालाँकि लिंकर प्रायः एम्बेडेड सिस्टम में इस उद्देश्य के लिए एक बेहतर उपकरण है)।

    const double PI = 3.14;
  • मान द्वारा पारित पैरामीटर के लिए फ़ंक्शन प्रोटोटाइप में कभी भी कास्ट का उपयोग न करें । इसका कोई अर्थ नहीं है और इसलिए यह केवल 'शोर' है।

    // don't add const to 'value' or 'size'
    int find(const int *data, size_t size, const int value); 
  • जहाँ उपयुक्त हो, const volatileउन स्थानों पर उपयोग करें जिन्हें प्रोग्राम द्वारा नहीं बदला जा सकता है लेकिन फिर भी बदल सकते हैं। हार्डवेयर रजिस्टर यहां विशिष्ट उपयोग के मामले हैं, उदाहरण के लिए एक स्थिति रजिस्टर जो एक डिवाइस स्थिति को दर्शाता है:

    const volatile int32_t *DEVICE_STATUS =  (int32_t*) 0x100;

अन्य उपयोग वैकल्पिक हैं। उदाहरण के लिए, फ़ंक्शन कार्यान्वयन के भीतर एक फ़ंक्शन के मापदंडों को कॉस्ट के रूप में चिह्नित किया जा सकता है।

// 'value' and 'size can be marked as const here
int find(const int *data, const size_t size, const int value)  
{
     ... etc

या फ़ंक्शन मान या गणनाएँ जो प्राप्त की जाती हैं और फिर कभी नहीं बदलती हैं:

char *repeat_str(const char *str, size_t n) 
{
    const size_t len = strlen(str);
    const size_t buf_size = 1 + (len * n);
    char *buf = malloc(buf_size);
    ...

ये constसंकेत केवल ये संकेत देते हैं कि आप परिवर्तनशील नहीं होंगे; वे परिवर्तन नहीं करते कि चर कैसे या कहाँ संग्रहीत किया जाता है। कंपाइलर निश्चित रूप से काम कर सकता है कि एक चर नहीं बदला गया है, लेकिन constआपको जोड़कर वह इसे लागू करने की अनुमति देता है। यह पाठक की मदद कर सकता है और कुछ सुरक्षा को जोड़ सकता है (हालांकि यदि आपके कार्य बड़े या जटिल हैं कि इससे बहुत फर्क पड़ता है, तो आपको यकीनन कुछ समस्याएँ हैं)। संपादित करें - जैसे। नेस्टेड छोरों और कई लंबे या इसी तरह के चर नामों के साथ एक 200-लाइन घने कोडित फ़ंक्शन, यह जानकर कि कुछ चर कभी नहीं बदलते हैं, अंडरस्टैंडिंग को आसानी से कम कर सकते हैं। इस तरह के कार्यों को बुरी तरह से डिजाइन या मेनटेन किया गया है।


के साथ समस्या const। आप शायद "कब्ज विषाक्तता" शब्द सुनेंगे। यह तब होता है जब constकिसी फंक्शन पैरामीटर में जोड़ने से 'कब्ज' फैलता है।

संपादित करें - कास्ट पॉइज़निंग: उदाहरण के लिए फ़ंक्शन में:

int function_a(char * str, int n)
{
    ...
    function_b(str);
    ...
}

यदि हम बदलते strहैं const, तो हमें यह सुनिश्चित करना चाहिए कि fuction_bयह भी एक लेता है const। और इसलिए यदि आप पर function_bगुजरता strहै function_c, आदि। जैसा कि आप कल्पना कर सकते हैं कि यह दर्दनाक हो सकता है अगर यह कई अलग-अलग फ़ाइलों / मॉड्यूलों में फैलता है। यदि यह एक ऐसे फ़ंक्शन में फैलता है जिसे बदला नहीं जा सकता है (जैसे सिस्टम लाइब्रेरी), तो एक कास्ट आवश्यक हो जाता है। तो constमौजूदा कोड में चारों ओर छिड़क शायद परेशानी पूछ रहा है। नए कोड में, हालांकि, constजहां उपयुक्त हो, लगातार योग्य होना सर्वोत्तम है ।

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

const char str[] = "hello world\n";
char *s = strchr(str, '\n');
*s = '\0';

strchrरिटर्न ए char*नहीं const char*। इसके कॉल पैरामीटर है के रूप में constयह चाहिए डाली करने के लिए कॉल पैरामीटर char*। और इस मामले में जो वास्तविक रीड-ओनली स्टोरेज प्रॉपर्टी बनाता है। संपादित करें: - यह आम तौर पर रीड-ओनली मेमोरी में var पर लागू होता है। 'रॉम' से मेरा मतलब केवल शारीरिक रॉम नहीं है, बल्कि कोई भी मेमोरी जो राइट-प्रोटेक्टेड है, जैसा कि एक विशिष्ट ओएस पर चलने वाले प्रोग्राम्स के कोड सेक्शन में होता है।

कई मानक लाइब्रेरी फ़ंक्शंस एक ही तरह से व्यवहार करते हैं, इसलिए सावधान रहें: जब आपके पास वास्तविक स्थिरांक हैं (यानी रोम में संग्रहीत) तो आपको अपने कब्ज़ को खोने के लिए नहीं बहुत सावधान रहना चाहिए।


यह वास्तव में दो अर्थ नहीं है। यह सिर्फ मतलब है, जैसा कि आप कहते हैं, " मैं इसे बदलने नहीं जा रहा हूं ।" उदाहरण के लिए, यह एक const volatileचर के लिए पूरी तरह से मान्य है ।
det

2
यह फंक्शन पैरामीटर्स का सही है लेकिन फ़ाइल स्कोप में स्थिरांक के लिए, उदाहरण के लिए, एक constचर वास्तव में केवल पढ़ने के लिए है: const"यह संशोधित नहीं किया जा सकता है"। const volatileदूसरी ओर A कहता है कि " इसे संशोधित नहीं किया जा सकता है, लेकिन यह बदल सकता है"। मैं अपने उत्तर में अस्थिरता का उल्लेख जोड़ूंगा।
विलियम मोरिस

मैं आपकी टिप्पणी से सहमत नहीं हूँ, सिर्फ इस विचार से कि यह कंपाइलर को ROM में डालने के लिए एक निर्देश है। इसका मतलब है कि अपरिभाषित व्यवहार के खिलाफ कुछ समय के लिए रनटाइम गार्ड (यानी किसी तरह से एक कॉन्स्टीट्यूशन को संशोधित करना), जिससे गलतफहमी पैदा हो सकती है जैसे "मैं constएक गैर- constपॉइंटर के माध्यम से इस चर को क्यों बदल सकता हूं " (एसओ और प्रत्येक अन्य सी फोरम पर एक सामान्य प्रश्न) !)। कुल मिलाकर मैं इस उत्तर यद्यपि :) की तरह
detly

आप सही हैं, "इसे रॉम में डालें" गलत है (हालाँकि succinct :-) - मैं इसे "इसे संशोधित नहीं किया जा सकता", जो अधिक सटीक है। आपकी टिप्पणियों के लिए आभार।
विलियम मोरिस

यह एक महान परिदृश्य है। मैं इसे वाक्यांश के लिए पसंद करता हूं जो constकेवल पढ़ने के लिए डेटा और डेटा के केवल-पढ़ने वाले दोनों विचारों को घोषित करता है - अंतर "इसे संशोधित नहीं किया जा सकता" बनाम "आप इसे संशोधित नहीं कर सकते"।
जॉन पुरडी

8

आम तौर पर किसी भी प्रोग्रामिंग भाषा में इसका उपयोग करने के लिए constया इसके बाद के समकक्ष संशोधक की सिफारिश की जाती है

  • यह कॉल करने वाले को स्पष्ट कर सकता है कि वे जो पारित कर चुके हैं वह बदलने वाला नहीं है
  • संभावित गति में सुधार होता है क्योंकि कंपाइलर को कुछ के लिए पता होता है कि यह कुछ चीजों को छोड़ सकता है जो केवल प्रासंगिक हैं यदि पैरामीटर बदल सकता है
  • अपने आप से सुरक्षा गलती से मूल्य बदल रहा है

1

हां, यह मूल रूप से TheLQ का जवाब है।

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

आमतौर पर जो मैंने देखा है, यह ज्यादातर कोड में निरंतर मूल्यों को जोड़ने के लिए उपयोग किया जाता है, और यह इंगित करने के लिए कि किसी विशेष फ़ंक्शन को कॉल करने पर सरणी या संरचना को संशोधित नहीं किया जाएगा। यह अंतिम भाग महत्वपूर्ण है, क्योंकि जब आप किसी फ़ंक्शन को कॉल करते हैं जो आपके सरणी या संरचना को संशोधित करेगा, तो आप मूल संस्करण को रखना चाह सकते हैं, इसलिए आप चर की एक प्रति बनाएँ और फिर इसे फ़ंक्शन में पास करें। यदि ऐसा नहीं है, तो आपको कॉपी की आवश्यकता नहीं है, जाहिर है, इसलिए उदाहरण के लिए आप बदल सकते हैं,

int foo(Structure s);

सेवा

int foo(const Structure * s);

और कॉपी ओवरहेड नहीं हो रही है।

बस जोड़ने के लिए, ध्यान दें कि सी के पास विशेष विनिर्देश हैं। उदाहरण के लिए,

int b = 1;
const int * a = &b;

के रूप में ही नहीं है

int b = 1;
int * const a = &b;

पहला कोड आपको संशोधित करने की अनुमति नहीं देगा। दूसरे मामले में, पॉइंटर स्थिर है, लेकिन इसकी सामग्री नहीं है, इसलिए कंपाइलर आपको * a = 3;संकलक त्रुटि के बिना कहने की अनुमति देगा , लेकिन आप aकिसी अन्य चीज़ का संदर्भ नहीं बना सकते ।


0

TheLQ के बयानों के साथ समझौता:

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

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