C ++ भाषा जाल

प्रोग्रामिंग भाषाओं के विभिन्न स्पष्ट "विशेषताओं" का वर्णन करते हुए लेखों की एक श्रृंखला बनाना अच्छा होगा। सबसे पहले, "पूर्वाभास का अर्थ है सशस्त्र", और दूसरी बात, उन्हें जानना आपको भाषा को बेहतर ढंग से समझने और समझाने की अनुमति देता है, अगर कुछ होता है, तो वे क्यों खतरनाक हैं। यहां तक ​​कि अगर इस तरह के निर्माणों को अपने स्वयं के कोड में उपयोग नहीं किया जाता है, तो किसी अन्य के कोड को पार्स करने या किसी टीम में काम करने पर इन जालों का सामना किया जा सकता है।

तो, इसे C ++ होने दें और char टाइप करें।

समस्याओं के मुख्य स्रोत हैं:


पहले आइटम पर अधिक। चूंकि कोई "देशी प्रकार" byte , इसलिए इसे char प्रकार का उपयोग करके बनाया गया है। स्टैंडर्ड विशेष रूप से स्पष्ट करता है कि प्रकार char , signed char और unsigned char प्रकार हैं। अन्य पूर्णांक प्रकारों में यह गुण नहीं होता है, उदाहरण के लिए, int और signed int समान परिभाषाएं हैं। यहां एक अतिरिक्त रेक तथ्य यह है कि चार्ट प्रकार को स्वयं या तो हस्ताक्षरित या अहस्ताक्षरित होना चाहिए - यह प्लेटफ़ॉर्म पर (मोटे तौर पर, कंपाइलर पर और इसकी कुंजी के सेट पर) निर्भर करता है। लेकिन एक ही समय में, वैसे भी, कंपाइलर उन सभी को एक दूसरे से अलग करने के लिए बाध्य है।

तदनुसार, ऐसी परिभाषा:
 void foo(char c); void foo(signed char c); void foo(unsigned char c); 

तीन अलग-अलग कार्यों की घोषणा करता है। समस्या जहां इन प्रकारों के विभिन्न गुणों के "मिश्रण" को दिखाया जा सकता है, उदाहरण के लिए, कोड के इस टुकड़े में:
 #include <iostream> #include <stdint.h> int main() { uint8_t b = 42; std::cout << b << std::endl; //   *,    42. } 

संक्षेप: कुछ स्थितियों में एक "बाइट" पूर्णांक प्रकार गैर-स्पष्ट परिणामों के साथ अपने "प्रतीकात्मक" सार को प्रकट कर सकता है।

चलो दूसरे बिंदु पर चलते हैं। सी में स्ट्रिंग्स के साथ काम करने के लिए कोई विशेष प्रकार नहीं है। सम्मेलन द्वारा, यह माना जाता है कि यदि हमारे पास एक char* (या const char* ) सूचक है, तो यह सबसे अधिक संभावना है कि यह एक स्ट्रिंग है, और इसे उपयुक्त कार्यों के लिए पारित किया जा सकता है। सादा C ऐसी आश्चर्यजनक चीजों की अनुमति देता है, उदाहरण के लिए, यह:
 int main(void) { char* ptr = "hello"; //   C,     ptr[1] = 'q'; //    "abcd"[1] = '2'; //    - ,     - read-only,           return 0; } 
अच्छी खबर यह है कि C ++ में यह "सुविधा" हस्तांतरित नहीं की गई थी।

लेकिन बाकी कहीं नहीं गए। उदाहरण के लिए, स्ट्रिंग शाब्दिक स्वयं के अंदर अशक्त वर्णों की अनुमति देता है (उदाहरण के लिए, "abc\0\123" ), और फ़ंक्शंस जो उनके साथ काम करने के लिए डिज़ाइन किए गए हैं ( strlen , आदि) ऐसे तार का समर्थन नहीं करते हैं। अर्थात्, इस निर्णय के कारण कि "सभी रेखाएं शून्य के साथ समाप्त होने वाले गैर-शून्य वर्णों का एक क्रम हैं", उन्हें तुरंत ऐसी स्थिति मिल गई कि सभी लाइनें जटिल ओ (एन) जैसे मज़ेदार प्रभावों को भी काम नहीं कर सकती थीं, जैसे कि "किसी दिए गए की लंबाई।" तार। "

इसके अलावा, चूंकि संकलक स्वचालित रूप से सभी स्ट्रिंग शाब्दिक के लिए '\0' जोड़ता है, तो यह निम्नलिखित परिणामों की ओर जाता है:
 char str1[] = "1234"; //    5 ,   4 char str2[4] = "1234"; // ,       char str3[4] = {'1', '2', '3', '4'}; // ...    

ऐसा लगता है कि सब ठीक है। लेकिन अंतिम पंक्ति में एक छिपी हुई रेक होती है - यह एक नियमित char* तरह दिखती है, अर्थात, इसे puts , strlen , आदि के लिए पास किया जा सकता है। और अपरिभाषित व्यवहार प्राप्त करें।

संक्षेप में: जब भी संभव हो, "पुराने" सी शैली में अपने सी ++ कार्यक्रमों में तार का उपयोग करने से बचें।

Source: https://habr.com/ru/post/In154033/


All Articles