2017-09-06 19 views
18

निम्नलिखित कार्यक्रम अपरिभाषित व्यवहार की वजह से व्यवस्थित विभाजन गलती भड़काती (एक स्ट्रिंग शाब्दिक को संशोधित करने की कोशिश कर):सी कंपाइलर क्यों शाब्दिक तारों के साथ असंगत प्रकारों के बारे में चेतावनी देते हैं?

int main() { 
    char *s = "immutable"; 
    s[0] = 'a'; 
    return 0; 
} 

फिर भी, वहाँ बिल्कुल कोई रास्ता जीसीसी/बजना बताने के लिए भी थोड़ी सी के बारे में चेतावनी फेंकना हो रहा है यह (-Wall -Wextra -pedantic -std=c11 कुछ भी मत करो)।

विशेष रूप से शुरुआती लोगों के लिए, इस तरह की स्थिति के बारे में सूचित करने के लिए उपयोगी होगा। यहां तक ​​कि गैर शुरुआती के लिए, कुछ थोड़ा कम स्पष्ट स्थितियों में यह सहायक हो सकता है:

void f(char *s) { 
    s[0] = '0'; 
} 

int main() { 
    char *s = "immutable"; 
    f("literal"); // oops 
    f(s); // oops 
    return 0; 
} 

इसके अलावा, इस सी प्रोग्रामिंग में कुछ const -culture लागू करने में मदद मिलेगी।

ऐसे मामलों को जानबूझकर क्यों नजरअंदाज कर दिया जाता है? क्या मानक सक्रिय रूप से निदानों को ऐसे मामलों में उत्सर्जित करने से रोकता है, या यह ज्यादातर पिछड़ा-संगतता के लिए है (अब उन्हें लागू करने की कोशिश कर रहा है बहुत अधिक चेतावनियां उत्पन्न करेगा)?

+0

यह डिफ़ॉल्ट रूप से चालू नहीं है क्योंकि दुख की बात है कि अभी भी गैर-कॉन्स सही फैशन में लिखे गए विरासत कोड के ढेर हैं। कुछ भी 'const' को सी – StoryTeller

+1

में जोड़ने की भविष्यवाणी करते हैं डिफ़ॉल्ट रूप से ऐसी चेतावनी को सक्षम करने से अलार्म थकान हो जाएगी। यह अच्छा होगा कि कंपेलरों ने इसके लिए चेतावनी दी है लेकिन अभी भी बहुत पुराना कोड है जो अभी भी सही कोड होने पर इस पर यात्रा करेगा। – Art

उत्तर

16

टीएल; डीआर सी कंपाइलर चेतावनी नहीं देते हैं, क्योंकि वे वहां कोई समस्या नहीं देखते हैं। परिभाषा के अनुसार, सी स्ट्रिंग अक्षर शून्य से char सरणी समाप्त कर दिए जाते हैं। यह केवल कहा गया है कि,

[...] कार्यक्रम इस तरह के एक सरणी संशोधित करने के लिए प्रयास करता है, व्यवहार अनिर्धारित रहता है।

तो, संकलन की प्रक्रिया में है, यह संकलक है कि एक char सरणी एक स्ट्रिंग शाब्दिक या स्ट्रिंग के रूप में व्यवहार करना चाहिए करने के लिए नहीं जाना जाता है। केवल संशोधन का प्रयास प्रतिबंधित प्रतिबंधित है।

संबंधित पढ़ें: दिलचस्पी लेने वाले किसी के लिए, Why are C string literals read-only?

यही कहा, मैं बहुत यकीन नहीं है कि यह एक अच्छा विकल्प है नहीं कर रहा हूँ देखते हैं, लेकिन gcc-Wwrite-strings का विकल्प है।

का हवाला देते हुए online manual,

-Wwrite-strings

जब सी संकलन, स्ट्रिंग देना प्रकार const char[length] ताकि गैर const char * सूचक में एक के पते को कॉपी एक चेतावनी का उत्पादन स्थिरांक। ये चेतावनियां आपको संकलित समय कोड में खोजने में मदद करती हैं जो एक स्ट्रिंग स्थिर में लिखने का प्रयास कर सकती है, लेकिन केवल तभी जब आप घोषणाओं और प्रोटोटाइप में कॉन्स्ट का उपयोग करने के बारे में बहुत सावधान रहें। अन्यथा, यह सिर्फ एक उपद्रव है। यही कारण है कि हमने -Wall इन चेतावनियों का अनुरोध नहीं किया।

तो, यह एक चेतावनी पिछले दरवाजे तरह से उपयोग करते हुए पैदा करता है।

परिभाषा के अनुसार, सी स्ट्रिंग अक्षर (यानी, वर्ण स्ट्रिंग अक्षर) char शून्य टर्मिनेटर के साथ सरणी हैं। मानक उन्हें const योग्यता के लिए जरूरी नहीं है।

रेफरी: C11, अध्याय

अनुवाद चरण 7 में, एक बाइट या शून्य मूल्य का कोड प्रत्येक multibyte चरित्र अनुक्रम कि एक स्ट्रिंग से परिणाम शाब्दिक या शाब्दिक में जोड़ा जाता है। मल्टीबाइट कैरेक्टर अनुक्रम का उपयोग तब स्थिर स्टोरेज अवधि और लंबाई की एक सरणी को प्रारंभ करने के लिए किया जाता है, जो अनुक्रम को रखने के लिए पर्याप्त है। चरित्र स्ट्रिंग अक्षर के लिए, सरणी तत्वों में टाइप char है, और मल्टीबाइट वर्ण अनुक्रम के व्यक्तिगत बाइट्स के साथ आरंभ किया गया है। [....]

पूर्वोक्त विकल्प का उपयोग स्ट्रिंग शाब्दिकconst योग्य तो एक स्ट्रिंग एक गैर स्थिरांक प्रकार सूचक को असाइनमेंट की आरएचएस के रूप में शाब्दिक का उपयोग कर एक चेतावनी चलाता है बनाता है।

यह C11 के संदर्भ में, अध्याय §6.7.3

एक प्रयास गैर const- के साथ एक lvalue के उपयोग के माध्यम से एक वस्तु एक स्थिरांक योग्य प्रकार से परिभाषित संशोधित करने के लिए किया जाता है के साथ किया जाता योग्य प्रकार, व्यवहार अपरिभाषित है। [...]

तो, यहाँ संकलक गैर const -qualified प्रकार के const योग्य प्रकार के कार्य के लिए एक चेतावनी पैदा करता है।

क्यों -Wall -Wextra -pedantic -std=c11 का उपयोग कर इस चेतावनी का उत्पादन नहीं करता करने के लिए संबंधित, एक बार फिर बोली के हवाले से, है

[...] इन चेतावनियों आप संकलन समय कोड है कि एक में लिखने के लिए कोशिश कर सकते हैं पर खोजने में मदद स्ट्रिंग स्थिर, लेकिन केवल तभी जब आप घोषणाओं और प्रोटोटाइप में कॉन्स्ट का उपयोग करने के बारे में बहुत सावधान रहें। अन्यथा, यह सिर्फ एक उपद्रव है। यही कारण है कि हमने -Wall इन चेतावनियों का अनुरोध नहीं किया।

+0

* "अन्यथा, यह सिर्फ एक उपद्रव है।" * ऐसा लगता है कि जो भी मैनुअल लिखता है वह अपने कोड के लिए बहाने का प्रयास कर रहा है: पी। – user694733

+0

umm ... शायद नहीं? कॉन्स्ट-टू-गैर-कॉन्स न तो अनुमति है और न ही निदान और निदान की गारंटी देता है। एक तरफ मजबूती से योग्यता प्राप्त करने से कुछ वैध कोड तोड़ सकते हैं, आपको पता है? –

+1

हां, आप विरासत कोड के साथ इस विकल्प का उपयोग नहीं कर सकते हैं। लेकिन किसी भी नए कोड को कॉन्स्ट-सही होने का प्रयास करना चाहिए। मुझे बस यह मजाकिया लगता है कि मैनुअल अत्यधिक रक्षात्मक लगता है। – user694733

14

इसके लिए एक विकल्प है: -Wwrite-strings। यह char[N] से const char[N] तक स्ट्रिंग अक्षर के प्रकार को बदलकर काम करता है। यह परिवर्तन मानक सी के साथ संगत नहीं है और वैध कोड को अस्वीकार कर देगा, और दुर्लभ मामलों में अमान्य कोड को चुपचाप स्वीकार किया जाएगा। यह डिफ़ॉल्ट रूप से सक्षम नहीं है।

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

+0

* "और दुर्लभ मामलों में अमान्य कोड को चुपचाप स्वीकार किया जाना चाहिए।" * यह कैसे होगा? यदि '-व्राइट-स्ट्रिंग्स' त्रुटि को अधिक सख्त जांचने में त्रुटि देता है, तो यह संभव नहीं होना चाहिए। – user694733

+4

@ user694733 कोड जो 'const char (*) []' चर के लिए शाब्दिक स्ट्रिंग का पता निर्दिष्ट करता है उसे चुपचाप स्वीकार किया जाएगा (जब तक कि मैंने पिछली बार चेक नहीं किया है), लेकिन मानक सी में, कोई अंतर्निहित रूपांतरण नहीं है 'char (*) []' से 'const '(*) []', इसलिए इसे डायग्नोस्टिक की आवश्यकता होती है। – hvd

+0

सुनिश्चित नहीं है कि कोई स्ट्रिंग अक्षर का पता क्यों लेगा, लेकिन मुझे लगता है कि आप सही हैं। मुझे अभी भी लगता है कि सामान्य मामले 'char * a = "x";' के बारे में चेतावनी, संभावित समस्या से बाहर निकलती है। – user694733

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