2012-04-22 24 views
13

मुझे पता है कि उदाहरण के लिए "hello" टाइप const char* है। तो मेरी प्रश्न हैं:एक char * को एक कॉन्स char * असाइन करना क्यों संभव है?

  1. हम कैसे एक गैर const char* इस तरह के "hello" की तरह एक शाब्दिक स्ट्रिंग असाइन कर सकते हैं:

    char* s = "hello"; // "hello" is type of const char* and s is char* 
            // and we know that conversion from const char* to 
            // char* is invalid 
    
  2. "hello" की तरह एक शाब्दिक स्ट्रिंग है, जो सभी में स्मृति ले जाएगा है मेरा प्रोग्राम, या यह अस्थायी चर की तरह है जो कथन समाप्त होने पर नष्ट हो जाएगा?

+2

यह केवल सी संगतता के लिए अनुमति है। आम तौर पर सी ++ में इसे बहिष्कृत माना जाता है और अच्छे कंपेलर चेतावनी देते हैं। – iammilind

उत्तर

22

वास्तव में, "hello" प्रकार char const[6] की है।

लेकिन प्रश्न का सारांश अभी भी सही है - क्यों सी ++ हमें एक गैर-const प्रकार पर केवल पढ़ने के लिए स्मृति स्थान असाइन करने की अनुमति देता है?

इसका एकमात्र कारण पुराने सी कोड के पीछे की संगतता है, जिसे const नहीं पता था। यदि सी ++ यहां सख्त था तो यह बहुत सारे मौजूदा कोड को तोड़ देता।

यह कहा गया है कि, अधिकांश कंप्यूटर्स को पर को ऐसे कोड के बारे में चेतावनी दी जा सकती है, जो डिफ़ॉल्ट रूप से बहिष्कृत या यहां तक ​​कि ऐसा भी करती है। इसके अलावा, सी ++ 11 इसे पूरी तरह से अस्वीकार करता है लेकिन संकलक अभी तक इसे लागू नहीं कर सकते हैं।


Standerdese प्रशंसक के लिए:
[रेफरी 1]सी ++ 03 मानक: §4.2/2

एक स्ट्रिंग शाब्दिक (2.13.4) नहीं एक विस्तृत है कि स्ट्रिंग शाब्दिक को "पॉइंटर टू चार" प्रकार के रैवल्यू में परिवर्तित किया जा सकता है; एक विस्तृत स्ट्रिंग अक्षर को "पॉइंटर से wchar_t" प्रकार के रैवल्यू में परिवर्तित किया जा सकता है। किसी भी मामले में, परिणाम सरणी के पहले तत्व के लिए एक सूचक है। यह रूपांतरण तभी माना जाता है जब कोई स्पष्ट उपयुक्त सूचक लक्ष्य प्रकार होता है, और जब एक सामान्यता से एक रावल्यू में परिवर्तित करने की सामान्य आवश्यकता होती है। [नोट: यह रूपांतरण को हटा दिया गया है। अनुलग्नक डी देखें।] ओवरलोड रिज़ॉल्यूशन (13.3.3.1.1) में रैंकिंग के उद्देश्य के लिए, इस रूपांतरण को एक योग्यता रूपांतरण (4.4) के बाद एक सरणी-से-पॉइंटर रूपांतरण माना जाता है। [उदाहरण: "एबीसी" को "पॉइंटर टू कॉन्स्ट चार" में एक सरणी-से-पॉइंटर रूपांतरण के रूप में परिवर्तित किया जाता है, और फिर योग्यता रूपांतरण के रूप में "पॉइंटर टू char" में परिवर्तित किया जाता है। ]

सी ++ 11 उपर्युक्त उद्धरण को हटा देता है जिसका अर्थ है कि यह सी ++ 11 में अवैध कोड है।

[रेफरी 2]C99 मानक 6.4.5/5 "स्ट्रिंग literals - शब्दार्थ":

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

यह निर्दिष्ट नहीं है कि ये सरणी अलग हैं या नहीं, उनके तत्वों के उचित मान हैं। यदि प्रोग्राम ऐसी सरणी को संशोधित करने का प्रयास करता है, तो व्यवहार अपरिभाषित है।

+1

मानक से प्रासंगिक उद्धरण जोड़े गए हैं। आशा है कि आप इसे ध्यान में रखेंगे। –

+0

डीबग मोड में एमएसवीसी आपको लिखने के समय रनटाइम पर एक स्ट्रिंग शाब्दिक, जीसीसी संकलन समय पर (यदि यह कर सकता है) पर रोक देगा। हालांकि, एक विकल्प है, मेरा मानना ​​है कि यह -इट्राइट-स्ट्रिंग्स या ऐसा है जो संगतता मोड को चालू करता है और आर/डब्ल्यू मेमोरी –

+2

@ एएलएस में स्ट्रिंग अक्षर डालता है आपने सादगी की बात ली है और इसे बदसूरत बना दिया है। ;-) लेकिन धन्यवाद।मैं वास्तव में इसे भी जोड़ना चाहता था लेकिन मुझे सी ++ 11 के अपने मसौदे में प्रासंगिक मार्ग नहीं मिल रहे हैं। 2.14.3 प्रकार को परिभाषित करता है, और अनुबंध रूपांतरण की अमान्यता को निर्दिष्ट करता है, लेकिन कुछ भी नहीं दिखाता है कि इसे बहिष्कृत किया गया था लेकिन C++ 03 में मान्य है। –

1

बस का उपयोग एक string:

std::string s("hello"); 

कि सी ++ तरीका होगा। यदि आपको वास्तव में char का उपयोग करना होगा, तो आपको एक सरणी बनाने और उस पर सामग्री की प्रतिलिपि बनाने की आवश्यकता होगी।

2

शाब्दिक स्ट्रिंग जैसे "हैलो" मेरे सभी कार्यक्रमों में स्मृति लेगा, यह सब एक अस्थायी चर की तरह है जो कथन समाप्त होने पर नष्ट हो जाएगा।

यह प्रोग्राम डेटा में रखा जाता है, इसलिए यह प्रोग्राम के जीवनकाल के भीतर उपलब्ध है। आप वर्तमान डेटा से इस डेटा के पॉइंटर्स और संदर्भ वापस कर सकते हैं।

const char* को char* पर डाला जा रहा है एकमात्र कारण char* सी के साथ comatiblity है, जैसे winapi सिस्टम कॉल। और इस कास्ट को किसी भी अन्य कास्टिंग कास्टिंग के विपरीत निष्पक्ष बनाया गया है।

+0

तो कॉन्स char * एकमात्र प्रकार है जिसे संकलक द्वारा char * unexplicitly में डाला जा सकता है। – AlexDan

+0

एलेक्सडैन, 'कॉन्स चार *' एकमात्र प्रकार है जिसे अपने गैर-कॉन्स फॉर्म में डाला जा सकता है (उदाहरण के लिए, 'const int * 'को' int * 'को अनजाने में नहीं डाला जा सकता है)। लेकिन आप एक waring उत्पन्न करने के लिए संकलक समायोजित कर सकते हैं। –

+2

भी, * कास्ट * एक अनियमित क्रिया है, 3 रूप: * कास्ट-कास्ट-कास्ट * –

-3

आपके उदाहरण में, आप असाइन नहीं कर रहे हैं, लेकिन निर्माण कर रहे हैं। std :: string, उदाहरण के लिए, std::string(const char *) कन्स्ट्रक्टर है (वास्तव में यह अधिक जटिल है, लेकिन इससे कोई फर्क नहीं पड़ता)। और, इसी तरह, char * (यदि यह एक प्रकार के सूचक के बजाय एक प्रकार था) तो एक कॉन्स char * कन्स्ट्रक्टर हो सकता है, जो स्मृति की प्रतिलिपि बना रहा है।

मुझे वास्तव में यह नहीं पता कि संकलक वास्तव में कैसे काम करता है, लेकिन मुझे लगता है कि यह ऊपर वर्णित जैसा ही हो सकता है: "Hello" की एक प्रति स्टैक में बनाई गई है और s इस प्रतिलिपि के पते के साथ शुरू किया गया है।

+2

यह बस सही नहीं है। कोई प्रतिलिपि नहीं बनाई जाती है, और सूचक के माध्यम से स्ट्रिंग को संशोधित करना यूबी है। –

+0

ढेर पर "हैलो" की कोई प्रति नहीं है! यह एक स्ट्रिंग अक्षर है जो कुछ वैश्विक [डेटा सेगमेंट] (https://secure.wikimedia.org/wikipedia/en/wiki/Data_segment) में बनाया जाएगा (लेकिन यह एक कार्यान्वयन विशिष्ट विवरण है)। – Praetorian

+0

@ कोनराड रुडॉल्फ, मैंने कभी नहीं कहा कि यह सही था। मुझे दुख है, यह ऐसा हो सकता है। वैसे भी लिंक के लिए धन्यवाद। – Steed

1

आपके दूसरे प्रश्न का उत्तर यह है कि परिवर्तनीय s रैम में टाइप पॉइंटर-टू-चार के रूप में संग्रहीत किया जाता है। यदि यह वैश्विक या स्थैतिक है, तो इसे ढेर पर आवंटित किया जाता है और चल रहे कार्यक्रम के जीवन के लिए वहां रहता है। यदि यह एक स्थानीय ("ऑटो") चर है, तो इसे स्टैक पर आवंटित किया जाता है और वर्तमान फ़ंक्शन लौटने तक वहां रहता है। किसी भी मामले में, यह सूचक को पकड़ने के लिए आवश्यक स्मृति की मात्रा पर कब्जा करता है।

स्ट्रिंग "Hello" एक स्थिर है, और यह अन्य सभी स्थिरांक और प्रारंभकर्ताओं के साथ प्रोग्राम के हिस्से के रूप में संग्रहीत है। यदि आपने उपकरण पर चलाने के लिए अपना प्रोग्राम बनाया है, तो स्ट्रिंग रोम में संग्रहीत की जाएगी।

ध्यान दें कि, क्योंकि स्ट्रिंग स्थिर है और s एक सूचक है, कोई प्रतिलिपि आवश्यक नहीं है। पॉइंटर s जहां स्ट्रिंग को संग्रहीत किया जाता है, वहां बस इंगित करता है।

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

  • कोई संबंधित समस्या नहीं^_^