2011-01-13 6 views
6

मैं जीएनयू वैज्ञानिक पुस्तकालय स्रोत कोड का अध्ययन किया गया है और मैं घोषणाओं निम्न प्रकार देखकर रखना:C99 स्थिरांक पारित-दर-मूल्य

double cblas_ddot (const int N, const double * x, const int incx, const double * y, const int incy) 

C99 में, वहाँ किसी भी (optimizational) के लाभ है उपरोक्त उदाहरण में मान द्वारा पारित एक तर्क घोषित किया गया है (उदाहरण के लिए N या incy) const? वैसे भी उनमें से एक प्रतिलिपि बनाई गई है, क्योंकि वे मूल्य से गुजर चुके हैं, है ना?

Thx! कॉर्नेल

उत्तर

11

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

गैर-स्मार्ट कार्यान्वयन में ऐसी घोषणा शायद किसी फ़ंक्शन को रेखांकित करने पर निर्णय पर असर डाल सकती है। लेकिन मुझे लगता है कि आजकल कंपाइलर्स इस तरह के निर्णय लेते हैं कि वे सीधे कार्य की परिभाषा से क्या करते हैं।

यह निश्चित रूप से भाषा के प्रतिबंध के रूप में देखा जा सकता है कि कार्यान्वयन का यह विनिर्देश इसके इंटरफ़ेस में व्यक्त किया गया है।

3

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

3

जैसा कि अन्य ने कहा है, कार्यों को इस तरह घोषित किया गया है कि, कार्य के दायरे में, वह चर बदलने योग्य नहीं होगा और ऐसा करने में, आपके कंपाइलर को आपको चेतावनी दी जानी चाहिए।

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

उदाहरण से, इस पर विचार करें:

#include <stdio.h> 

void add(int* result, const int* x, int* y) 
{ 
    *result = *x + *y; 
    (*y)++; /* <-- the caller won't expect this! */ 

} 

int main(int argc, char** argv) 
{ 
    int a = 7; 
    int b = 10; 
    int c = 0; 

    add(&c, &a, &b); 

    printf("%d + %d = %d\n", a, b, c); 
    return 0; 
} 

यह 7+11=17 बाहर थूक। अब इस एक छोटी सी, गैर गंभीर मामला है लेकिन थे हम कुछ भी महत्वपूर्ण पर निर्भर होने के लिए चीजों के सभी प्रकार के हो सकता है ...

आप y चर के खिलाफ स्थिरांक छड़ी हैं, तो आप मिलना चाहिए:

constexample.c: In function ‘add’: constexample.c:7:5: error: increment of read-only location ‘*y’

संपादित करें, आगे स्पष्टीकरण के लिए:

एक अच्छे कारण के लिए एक गैर-सूचक चर के लिए एक const प्रकार की घोषणा करने के एक चर है कि कुछ के आकार, या किसी भी चर कि एक सरणी का अधिकतम मान रखती है का प्रतिनिधित्व करता है के लिए है। पर विचार करें:

int editstring(char* result, ..., const char* source, const size_t source_len); 

अब, आप अपने आप से कहते हैं, लेकिन मैं source_len संपादित कभी नहीं चाहते हैं। खैर, आइए आपके एल्गोरिदम में जो भी कारण हो, आप कहते हैं। यदि आपका परिवर्तन source_len का मान बढ़ाता है, तो आप जो आवंटित किए गए हैं उससे परे स्मृति तक पहुंचने का जोखिम चलाते हैं .. const सेट करने पर आप उस मान को संशोधित करने का प्रयास करते समय एक कंपाइलर त्रुटि उत्पन्न करेंगे।

मुझे दोहरी रेखांकित में इंगित करना चाहिए, कि कॉन्स केवल कंपाइलर को कहने का एक तरीका है "मैं इसे संपादित नहीं करने का वादा करता हूं"। यह गारंटी नहीं देता है कि स्मृति केवल पढ़ने के लिए है, लेकिन यह आपके इरादे को चिह्नित करने का एक तरीका है जैसे कि आप त्रुटियों को फँसते हैं। यदि आपको इसे संशोधित करने की आवश्यकता नहीं है, तो इसे घोषित करें।

और जब से आपने पूछा, दोनों संस्करणों द्वारा उत्पन्न असेंबली समान है।

+2

अपने उदाहरण में आप पैरामीटर 'कॉन्स्ट' घोषित नहीं करते हैं लेकिन डेटा पैरामीटर पॉइंट्स को इंगित करता है। पॉइंटर्स के लिए ओपी ने पूछा कि 'int * const result' जैसा कुछ होगा। साथ ही, अगर मुझे सही याद है, तो '* y ++' पहले पॉइंटर को बढ़ाता है और फिर इसे अस्वीकार करता है। कॉलर को परेशान करने वाला कुछ भी नहीं होता, नहीं? –

+0

आप सही हैं, मेरी गलती, '(* y) ++ होनी चाहिए; 'हालांकि, मैंने कभी नहीं कहा कि मेरे पैरामीटर कॉन्स को घोषित करने से सूचक को प्रभावित होता है - वास्तव में, मेरे उदाहरण का * बिंदु * यह है कि यह बदलता है स्रोत स्मृति मैंने हालांकि मानक परिवर्तनीय consts की उपयोगिता पर एक अतिरिक्त खंड जोड़ा है। –