2010-08-19 16 views
7
int main(void) 
{ 
    char four[4] = "four"; 
    return 0; 
} 

जब एक सी के रूप में संकलित ++ कार्यक्रम, जी ++ रिपोर्टचार चार [4] = "चार"; इस कथन के लिए सही अर्थशास्त्र क्या हैं?

xxx.cpp: समारोह int मुख्य():

xxx.cpp: 3: त्रुटि: की सरणी के लिए प्रारंभकर्ता-स्ट्रिंग वर्ण बहुत लंबा

संकलित आ सी कार्यक्रम, जीसीसी कोई त्रुटि की रिपोर्ट जब है।

यह मेरे लिए प्रकट होता है, कि काम सही ढंग से चर में सभी 4 बाइट को कॉपी कर रहा है, जैसा कि मैंने उम्मीद की थी।

तो मेरे सवाल करने पर निर्भर करता .....

सी में मनाया व्यवहार सही है या मैं एक अपरिभाषित व्यवहार कहीं छू रहा है, या यह कुछ और पूरी तरह है?

+1

उत्तर के साथ एक बहुत ही समान प्रश्न है जो इस प्रश्न को यहां फिट करता है: http://stackoverflow.com/questions/3216462/initializing-char-arrays-in-a-way-similar-to-initializing-string-literals –

+0

इसे खोजने पर बधाई। हां यह इस मुद्दे पर थोड़ा सा चर्चा करता है। – EvilTeach

उत्तर

22

लघु जवाब: अपने कोड मान्य सी है, लेकिन नहीं वैध C++ है।

लांग aswer:

"four" वास्तव में 5 वर्णों है - वहाँ है एक \0 आप के लिए वहाँ गयी। अनुभाग 6.7.8 प्रारंभ, पैरा 13 में, सी मानक का कहना है:

An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

तो \0 बस जब यह सी सी ++ के रूप में संकलित किया गया है इसे दूसरे तरीके से इलाज किया जाता है अपने कार्यक्रम में नजरअंदाज कर दिया है। वास्तव में, इस विशेष मामले (धारा 8.5.2 चरित्र सरणियों, पैरा 2) बाहर कहा जाता है स्पष्ट सी ++ कल्पना में: चार पत्र:

There shall not be more initializers than there are array elements. [ Example:

char cv[4] = "asdf"; // error 

is ill-formed since there is no space for the implied trailing ’\0’ . — end example ]

+1

सी में यह मान्य है, लेकिन यह आपको कुछ स्तर पर चेतावनी देना चाहिए। – Joel

+0

@Joel, मुझे नहीं लगता कि एक चेतावनी होना चाहिए, मानक संकेत मिलता है कि यह पूरी तरह से सुरक्षित है और अच्छी तरह से परिभाषित है लगता है। –

+0

जबकि sizeof ("चार") 5 बाइट्स की है, केवल 4 बाइट चर को कॉपी किया मिलता है। – EvilTeach

2

स्ट्रिंग "चार" वास्तव में पाँच बाइट का है प्लस एक शून्य बाइट (\ 0) एक स्ट्रिंग टर्मिनेटर के रूप में। यह थोड़ी देर के बाद से मैंने सी या सी ++ लिखा है, लेकिन मुझे लगता है कि सी कंपाइलर चुपचाप किसी भी कारण से अनदेखा कर रहा है।

2

बेहतर होगा

char four[] = "four"; 
+0

जो सी और सी ++ दोनों में पांच-चार सरणी देता है, और बहुत अच्छा काम करता है। –

+0

@ डेविड, केवल अगर आप * पांच-अक्षर सरणी चाहते हैं। लेकिन अगर आपको परवाह नहीं है, तो इस तरह निश्चित रूप से अधिक रखरखाव योग्य है। –

+0

ठीक है, मैं दलील दूंगा कि आप लगभग चार चार [4] = "चार" कभी नहीं चाहते हैं। –

1

आप जो देख रहे सी और सी के बीच एक अंतर है ++। सी आपको अतिरिक्त प्रारंभकर्ताओं की अनुमति देता है, जिन्हें अनदेखा किया जाता है। सी ++ इस पर प्रतिबंध लगाता है - अगर आप एक स्ट्रिंग के लिए एक आकार (या सरणी) यह काफी बड़ी सभी initializers समायोजित करने के लिए होना चाहिए (NUL टर्मिनेटर सहित, एक स्ट्रिंग के मामले में) निर्दिष्ट करें, या कोड बीमार का गठन है (मानक के लिए "इसकी अनुमति नहीं है - संकलक को इसे अस्वीकार करने की अपेक्षा करें")।

+0

नहीं। मुझे लगता है कि अतिरिक्त एनयूएल को एक विशेष मामले के रूप में माना जाता है। यदि आप इसे चार चार [4] = "पांचX" बनाते हैं; आपको सी – EvilTeach

+0

@EvilTeach में एक त्रुटि मिलती है - मुझे एक चेतावनी मिलती है, त्रुटि नहीं, 'पांचX" केस के साथ। –

+0

@EvilTeach (और कार्ल): यह (काफी हद तक) मानकों के साथ एक कठिनाई पर वापस आता है: उन्हें गलत कोड के लिए "निदान" की आवश्यकता होती है (लेकिन अगर संकलक अभी भी चुनता है तो संकलक अभी भी स्वीकार कर सकता है), लेकिन यह उस पर निर्भर है एक डायग्नोस्टिक क्या है (या नहीं) परिभाषित करने के लिए संकलक। यह भी सामान्य है कि अनुरूप झंडे के अनुरूप विशिष्ट झंडे की आवश्यकता होती है, इसलिए आपको डिफ़ॉल्ट रूप से इतना अधिक नहीं मिल सकता है। –