2012-01-31 12 views
13

कल्पना कीजिए मैं इस सी समारोह (और एक हेडर फाइल में इसी प्रोटोटाइप)क्या यह एक फ़ंक्शन पैरामीटर की स्थिरता को दूर करने के लिए अपरिभाषित व्यवहार है?

void clearstring(const char *data) { 
    char *dst = (char *)data; 
    *dst = 0; 
} 

है वहाँ उपरोक्त कोड में अपरिभाषित व्यवहार है, दूर const कास्टिंग, या यह सिर्फ एक बहुत बुरा प्रोग्रामिंग अभ्यास है ?

मान लीजिए कोई स्थिरांक योग्य वस्तुओं

char name[] = "pmg"; 
clearstring(name); 
+2

यदि कास्ट यूबी नहीं है, तो मुझे लगता है कि यह होना चाहिए :) – pmg

+0

आपके पास निश्चित रूप से शॉटगन स्थलों में आपका पैर स्क्वायर है! –

+1

@pmg: अगर कास्ट स्वयं यूबी थे, तो भाषा को अनुमति देने वाली छोटी सी बात होगी - एक कंपाइलर के लिए यह पता लगाना आसान है कि एक कास्ट में 'कॉन्स्ट' जोड़ा गया है, वैसे ही यह पता चलता है कि' char * डीएसटी = डेटा; 'अवैध है। स्पष्ट रूप से कुछ बिंदुहीन चीजें हैं जो ऐतिहासिक कारणों के लिए मानक परमिट करती हैं, लेकिन मेरा दावा है कि यह उनमें से एक नहीं है :-) –

उत्तर

20

प्रयास इस्तेमाल किया *dst लिखने के लिए कर रहे हैं फोन करने वाले आप एक स्थिरांक वस्तु के लिए एक सूचक है, या एक स्ट्रिंग शाब्दिक के लिए सूचक गुजरता यूबी है।

लेकिन अगर कॉलर आपको डेटा के सूचक को पास करता है जो वास्तव में उत्परिवर्तनीय है, तो व्यवहार परिभाषित किया जाता है। एक const char* बनाना जो एक संशोधित char को इंगित करता है वह char अपरिवर्तनीय नहीं बनाता है।

तो:

char c; 
clearstring(&c); // OK, sets c to 0 
char *p = malloc(100); 
if (p) { 
    clearstring(p); // OK, p now points to an empty string 
    free(p); 
} 
const char d = 0; 
clearstring(&d); // UB 
clearstring("foo"); // UB 

है यही कारण है, अपने कार्य अत्यंत बीमार की सलाह दी है, क्योंकि यह इतना आसान है एक फोन करने वाले यूबी पैदा करने के लिए में। लेकिन वास्तव में परिभाषित व्यवहार के साथ इसका उपयोग करना संभव है।

+4

+1: (आईएम) उत्परिवर्तन वस्तु की एक अंतर्निहित संपत्ति है, भले ही योग्यता के बावजूद सूचक का उपयोग करने के लिए उपयोग किया जाता है ... – Christoph

+0

क्या यह यूबी 'सी 99 6.6 §9' या' सी 99 6.7.3 §5' की वजह से है? – Lundin

+1

@ लंदन: स्ट्रिंग अक्षर के मामले में उत्तरार्द्ध (और 6.4.5/6 6.7.3/5 के बजाय, क्योंकि स्ट्रिंग अक्षर सी में 'const' ऑब्जेक्ट नहीं हैं)। पता स्थिरांक के पास इसके साथ कुछ लेना देना नहीं है। –

0

strstr जैसे फ़ंक्शन पर विचार करें, यदि किसी स्ट्रिंग वाले किसी ऑब्जेक्ट के किसी हिस्से को पॉइंटर दिया जाता है, तो उसी ऑब्जेक्ट के संभवतः अलग-अलग हिस्से में पॉइंटर लौटाता है। यदि विधि को स्मृति के केवल पढ़ने के क्षेत्र में एक सूचक पास किया गया है, तो यह एक सूचक को स्मृति के केवल पढ़ने के क्षेत्र में वापस कर देगा; इसी प्रकार यदि इसे एक लिखने योग्य क्षेत्र में सूचक दिया जाता है, तो यह एक सूचक को एक लिखने योग्य क्षेत्र में वापस कर देगा।

सी में कोई रास्ता नहीं एक समारोह एक const char * लौटने जब एक const char * दिया है, और एक साधारण char * लौटने जब एक साधारण char * दिया करने के लिए नहीं है। के साथ संगत होने के लिए const char * भाषा के विचार से पहले काम किया गया था, इसे एक कॉन्स्ट-क्वालिफाइड पॉइंटर को गैर-कॉन्स्ट-क्वालिफाइड पॉइंटर में परिवर्तित करना होगा। हालांकि यह सच है कि लाइब्रेरी फ़ंक्शन strstr के रूप में ऐसा कोई कलाकार डालने का हकदार हो सकता है, भले ही उपयोगकर्ता कोड नहीं हो सकता है, वही पैटर्न अक्सर उपयोगकर्ता कोड में पर्याप्त होता है जो इसे प्रतिबंधित करना व्यावहारिक होगा।

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

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