क्या मुख्य () वास्तव में C ++ प्रोग्राम की शुरुआत है?


131

C ++ मानक से अनुभाग $ 3.6.1 / 1 पढ़ता है,

एक कार्यक्रम में एक वैश्विक फ़ंक्शन शामिल होगा जिसे मुख्य कहा जाता है , जो कार्यक्रम की निर्दिष्ट शुरुआत है।

अब इस कोड पर विचार करें,

int square(int i) { return i*i; }
int user_main()
{ 
    for ( int i = 0 ; i < 10 ; ++i )
           std::cout << square(i) << endl;
    return 0;
}
int main_ret= user_main();
int main() 
{
        return main_ret;
}

यह नमूना कोड वही करता है जो मैं इसे करने का इरादा रखता हूं, यानी पूर्णांक के वर्ग को 0 से 9 तक प्रिंट करने से पहले , इसमें प्रवेश करता हूंmain() फ़ंक्शन जो कि प्रोग्राम का "प्रारंभ" माना जाता है।

मैंने भी इसे संकलित किया -pedantic विकल्प के , जीसीसी 4.5.0। यह कोई त्रुटि नहीं देता, चेतावनी भी नहीं!

तो मेरा सवाल है,

क्या यह कोड वास्तव में मानक अनुरूप है?

यदि यह मानक अनुरूप है, तो क्या यह मानक अमान्य नहीं कहता है? main()इस कार्यक्रम की शुरुआत नहीं है! user_main()से पहले निष्पादितmain()

मैं समझता हूं कि वैश्विक चर को आरंभ करने के लिए main_ret, use_main()पहले निष्पादित होता है लेकिन यह पूरी तरह से एक अलग बात है; मुद्दा यह है कि, यह मानक से उद्धृत कथन $ 3.6.1 / 1 को अमान्य करता है, जैसा कि कार्यक्रम main()की शुरुआत नहीं है ; यह वास्तव में इस कार्यक्रम का अंत है !


संपादित करें:

आप 'स्टार्ट' शब्द को कैसे परिभाषित करते हैं?

यह वाक्यांश "कार्यक्रम की शुरुआत" की परिभाषा को उबालता है । तो आप इसे कैसे परिभाषित करते हैं?

जवाबों:


85

नहीं, C ++ मुख्य के कॉल से पहले "पर्यावरण को सेट" करने के लिए बहुत सी चीजें करता है; हालाँकि, मुख्य C ++ प्रोग्राम के "उपयोगकर्ता निर्दिष्ट" भाग की आधिकारिक शुरुआत है।

पर्यावरण सेटअप में से कुछ नियंत्रणीय नहीं है (एसटीडी सेट करने के लिए प्रारंभिक कोड की तरह :: cout; हालांकि, कुछ पर्यावरण स्थिर वैश्विक ब्लॉक की तरह नियंत्रणीय हैं (स्थिर वैश्विक चर को इनिशियलाइज़ करने के लिए)। ध्यान दें कि चूंकि आपके पास फुल नहीं है। मुख्य से पहले नियंत्रण, आपके पास उस क्रम पर पूर्ण नियंत्रण नहीं है जिसमें स्थिर ब्लॉकों को आरंभ किया जाता है।

मुख्य के बाद, आपका कोड वैचारिक रूप से कार्यक्रम के "पूरी तरह से नियंत्रण में" होता है, इस अर्थ में कि आप दोनों को किए जाने वाले निर्देशों को निर्दिष्ट कर सकते हैं और जिस क्रम में उन्हें प्रदर्शन करना है। मल्टी-थ्रेडिंग कोड निष्पादन आदेश को पुनर्व्यवस्थित कर सकता है; लेकिन, आप अभी भी C ++ के नियंत्रण में हैं क्योंकि आपने कोड निष्पादित (संभवतः) आउट-ऑफ-ऑर्डर के अनुभाग निर्दिष्ट किए हैं।


9
इसके लिए +1 "ध्यान दें कि चूंकि आपके पास मुख्य से पहले पूर्ण नियंत्रण नहीं है, इसलिए आपके पास उस क्रम पर पूर्ण नियंत्रण नहीं है जिसमें स्थैतिक ब्लॉक आरंभ हो जाते हैं। मुख्य के बाद, आपका कोड वैचारिक रूप से" पूरी तरह से नियंत्रण में है "" कार्यक्रम, इस अर्थ में कि आप दोनों को किए जाने वाले निर्देशों को निर्दिष्ट कर सकते हैं और जिस क्रम में उन्हें प्रदर्शन करना है " । यह मुझे इस उत्तर को स्वीकार किए गए उत्तर के रूप में चिह्नित करने के लिए भी बनाता है ... मुझे लगता है कि ये बहुत महत्वपूर्ण बिंदु हैं, जो कि "कार्यक्रम की शुरुआत" केmain() रूप में पर्याप्त रूप से उचित है
नवाज

13
@ नवाज़: ध्यान दें कि आरंभीकरण क्रम पर कोई पूर्ण नियंत्रण नहीं होने पर, आपके पास आरंभीकरण त्रुटियों पर कोई नियंत्रण नहीं है: आप एक वैश्विक दायरे में अपवादों को नहीं पकड़ सकते।
एंड्रे कैरन

@ नवाज़: स्थिर वैश्विक ब्लॉक क्या है? क्या आप इसे सरल उदाहरण का उपयोग करके समझाएंगे? धन्यवाद
नाशक

@meet: नेमस्पेस स्तर पर घोषित वस्तुओं की staticभंडारण अवधि होती है, और इस प्रकार, विभिन्न अनुवाद इकाइयों से संबंधित इन वस्तुओं को किसी भी क्रम में आरंभ किया जा सकता है (क्योंकि ऑर्डर) मानक द्वारा अनिर्दिष्ट है)। मुझे यकीन नहीं है कि यह आपके प्रश्न का उत्तर देता है, हालांकि इस विषय के संदर्भ में मैं यही कह सकता हूं।
नवाज

88

आप वाक्य को गलत तरीके से पढ़ रहे हैं।

एक कार्यक्रम में मुख्य नामक एक वैश्विक फ़ंक्शन शामिल होगा, जो कार्यक्रम की निर्दिष्ट शुरुआत है।

मानक शेष के प्रयोजनों के लिए "प्रारंभ" शब्द को परिभाषित कर रहा है। यह नहीं कहा जाता है कि कोई कोड निष्पादित होने mainसे पहले कहा जाता है। यह कहता है कि कार्यक्रम की शुरुआत समारोह में मानी जाती है main

आपका कार्यक्रम आज्ञाकारी है। जब तक मुख्य शुरू नहीं किया जाता है तब तक आपका कार्यक्रम "शुरू" नहीं हुआ है। आपके प्रोग्राम को "प्रारंभ" से पहले निर्माणकर्ता को मानक में "प्रारंभ" की परिभाषा के अनुसार कहा जाता है, लेकिन यह शायद ही मायने रखता है। कोड का एक बहुत पहले निष्पादित किया जाता mainहै कभी भी हर कार्यक्रम में बुलाया जाता है, न कि केवल इस उदाहरण के लिए।

चर्चा के प्रयोजनों के लिए, प्रोग्राम के 'प्रारंभ' से पहले आपके कंस्ट्रक्टर कोड को निष्पादित किया जाता है, और यह पूरी तरह से मानक के अनुरूप है।


3
क्षमा करें, लेकिन मैं उस खंड की आपकी व्याख्या से असहमत हूं।
ऑर्बिट

मुझे लगता है कि एडम डेविस सही है, "मुख्य" कुछ प्रकार के कोडिंग प्रतिबंधों की तरह है।
laike9m

@LightnessRacesinOrbit मैंने कभी भी फॉलो-अप नहीं किया, लेकिन मेरे लिए यह वाक्य तार्किक रूप से "एक वैश्विक फ़ंक्शन जिसे मुख्य प्रोग्राम की निर्दिष्ट शुरुआत है" (जोर दिया गया) कहा जा सकता है। उस वाक्य की आपकी क्या व्याख्या है?
एडम डेविस

1
@ एडमडाविस: मुझे याद नहीं कि मेरी चिंता क्या थी। मैं अब एक के बारे में नहीं सोच सकता।
को ऑर्बिट

23

आपका कार्यक्रम लिंक नहीं करेगा और इस तरह से नहीं चलेगा जब तक कि कोई मुख्य न हो। हालांकि मुख्य () प्रोग्राम के निष्पादन की शुरुआत का कारण नहीं बनता है क्योंकि फ़ाइल स्तर पर ऑब्जेक्ट्स में कंस्ट्रक्टर होते हैं जो पहले से चलते हैं और एक पूरा प्रोग्राम लिखना संभव होगा जो मुख्य () से पहले अपने जीवनकाल को चलाता है और पहुंच जाता है और मुख्य को ही एक खाली शरीर।

हकीकत में इसे लागू करने के लिए आपके पास एक ऐसी वस्तु होनी चाहिए जो मुख्य और उसके निर्माता से पहले कार्यक्रम के सभी प्रवाह को लागू करने के लिए बनाई गई हो।

इसे देखो:

class Foo
{
public:
   Foo();

 // other stuff
};

Foo foo;

int main()
{
}

आपके कार्यक्रम का प्रवाह प्रभावी ढंग से होगा Foo::Foo()


13
+1। लेकिन ध्यान दें कि यदि आपके पास विभिन्न अनुवाद इकाइयों में कई वैश्विक वस्तुएं हैं, तो यह आपको जल्दी से मुसीबत में डाल देगा क्योंकि निर्माणकर्ताओं को जिस क्रम में बुलाया जाता है वह अपरिभाषित है। आप सिंगलटन और आलसी इनिशियलाइज़ेशन से दूर हो सकते हैं, लेकिन एक मल्टीथ्रेडेड वातावरण में, चीजें बहुत जल्दी बदसूरत हो जाती हैं। एक शब्द में, वास्तविक कोड में ऐसा न करें।
अलेक्जेंड्रे सी।

3
जब भी आपको संभवतः अपने कोड में मुख्य () एक उचित निकाय देना चाहिए और इसे निष्पादन को चलाने की अनुमति देनी चाहिए, तो बाहर की वस्तुओं की अवधारणा जो शुरू होती है वह बहुत सारे LD_PRELOAD पुस्तकालयों पर आधारित होती है।
कैशोकॉ

2
@ एलेक्स: मानक अपरिभाषित कहते हैं, लेकिन व्यावहारिक मामले की कड़ी के आदेश के रूप में (आमतौर पर, संकलक पर निर्भर करता है) initiazation आदेश।
थॉमसमैकलॉड

1
@ थोमस: मैं निश्चित रूप से दूर से उस पर भरोसा करने की कोशिश नहीं करूंगा। मैं निश्चित रूप से निर्माण प्रणाली को मैन्युअल रूप से नियंत्रित करने की कोशिश नहीं करूंगा।
अलेक्जेंड्रे सी।

1
@ एलेक्स: अब इतना महत्वपूर्ण नहीं है, लेकिन दिन में हम बिल्ड ऑर्डर को नियंत्रित करने के लिए लिंक ऑर्डर का उपयोग करेंगे ताकि भौतिक मेमोरी पेजिंग को कम किया जा सके। ऐसे अन्य कारण हैं जिनकी वजह से आप प्रोग्राम के शब्दार्थों को प्रभावित नहीं कर सकते हैं, जैसे स्टार्टअप प्रदर्शन तुलना परीक्षण।
थॉमस मैकलेड

15

आपने प्रश्न को "सी" के रूप में भी टैग किया है, फिर, सी के बारे में कड़ाई से बोलते हुए, आपका प्रारंभ आईएसओ सी 99 मानक के 6.7.8 "प्रारंभिक" के अनुसार विफल होना चाहिए।

इस मामले में सबसे अधिक प्रासंगिक है # 4 बाधाएं जो कहती हैं:

किसी ऑब्जेक्ट के लिए इनिशियलाइज़र के सभी भाव जिसमें स्थिर स्टोरेज अवधि होती है, स्थिर अभिव्यक्ति या स्ट्रिंग शाब्दिक होगा।

तो, आपके प्रश्न का उत्तर यह है कि कोड सी मानक के अनुरूप नहीं है।

आप शायद "सी" टैग को हटाना चाहते हैं यदि आप केवल सी ++ मानक के लिए रुचि रखते थे।


4
@ Remo.D क्या आप हमें बता सकते हैं कि उस सेक्शन में क्या है। हम सभी का C मानक :) नहीं है।
उम्मागुम्मा

2
जब से आप इतने योग्य हैं: काश, ANSI C 1989 से अप्रचलित हो गया है। ISO C90 या C99 हवाला देने के लिए प्रासंगिक मानक हैं।
लुंडिन

@ लुंडिन: कोई भी कभी भी पर्याप्त नहीं है :) मैं आईएसओ C99 पढ़ रहा था, लेकिन मुझे पूरा विश्वास है कि यह C90 पर भी लागू होता है।
रेम। डी।

@एक दृश्य। आप सही हैं, मुझे लगता है कि वाक्य यहाँ सबसे अधिक प्रासंगिक है जोड़ा।
रेम। डी।

3
@ रेमो: +1 यह जानकारी प्रदान करने के लिए कि यह मान्य सी नहीं है; मुझे नहीं पता था कि यह देखें कि लोग कैसे सीखते हैं, कभी योजना से, कभी संयोग से!
नवाज

10

धारा 3.6 एक संपूर्ण के रूप में mainऔर गतिशील आरंभीकरण की बातचीत के बारे में बहुत स्पष्ट है। "प्रोग्राम की निर्दिष्ट शुरुआत" का उपयोग कहीं और नहीं किया जाता है और यह केवल सामान्य इरादे का विवरणात्मक है main()। इसका मतलब यह नहीं है कि एक वाक्यांश को एक मानक तरीके से व्याख्या करना है जो मानक में अधिक विस्तृत और स्पष्ट आवश्यकताओं के विपरीत है।


9

कंपाइलर को अक्सर मानक कंप्लेंट होने के लिए मुख्य () से पहले कोड जोड़ना पड़ता है । क्योंकि मानक निर्दिष्ट करता है कि ग्लोबल्स / स्टैटिक्स का टीकाकरण पहले किया जाना चाहिए कार्यक्रम निष्पादित । और जैसा कि उल्लेख किया गया है, वही फ़ाइल स्कोप (ग्लोबल्स) में रखी गई वस्तुओं के निर्माणकर्ताओं के लिए जाता है।

इस प्रकार मूल प्रश्न सी के लिए भी प्रासंगिक है, क्योंकि एक सी कार्यक्रम में आपके पास अभी भी ग्लोबल्स / स्थैतिक आरंभीकरण होगा जिससे कार्यक्रम शुरू किया जा सके।

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

संपादित करें: उदाहरण के लिए देखें आईएसओ 9899: 1999 5.1.2:

स्थैतिक भंडारण अवधि वाली सभी वस्तुओं को प्रोग्राम स्टार्टअप से पहले आरंभीकृत (उनके प्रारंभिक मूल्यों पर सेट) किया जाएगा। इस तरह के इनिशियलाइज़ेशन का तरीका और समय अन्यथा अनिर्दिष्ट है।

यह "जादू" कैसे किया जाए इसके पीछे का सिद्धांत सी के जन्म के बाद वापस चला जाता है, जब यह एक प्रोग्रामिंग भाषा थी जिसका उपयोग केवल रैम-आधारित कंप्यूटरों पर UNIX OS के लिए किया जाना था। सिद्धांत रूप में, प्रोग्राम निष्पादन योग्य फ़ाइल से सभी प्री-इनिशियलाइज्ड डेटा को रैम में लोड करने में सक्षम होगा, उसी समय जब प्रोग्राम स्वयं रैम पर अपलोड किया गया था।

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

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

इसलिए, बहुत अधिक हर C / C ++ प्रोग्राम में कुछ init / "copy-down" कोड होता है जिसे मुख्य के पहले निष्पादित किया जाता है, मानकों के आरंभीकरण नियमों के अनुरूप करने के लिए।

एक उदाहरण के रूप में, एम्बेडेड सिस्टम में आमतौर पर "नॉन-आईएसओ कंप्लेंट स्टार्टअप" नामक एक विकल्प होता है जहां प्रदर्शन कारणों से पूरे प्रारंभिक चरण को छोड़ दिया जाता है, और फिर कोड वास्तव में सीधे मुख्य से शुरू होता है। लेकिन इस तरह के सिस्टम मानकों के अनुरूप नहीं हैं, क्योंकि आप वैश्विक / स्थिर चर के init मूल्यों पर भरोसा नहीं कर सकते हैं।


4

आपका "प्रोग्राम" केवल एक वैश्विक चर से एक मूल्य देता है। बाकी सब कुछ इनिशियलाइज़ेशन कोड है। इस प्रकार, मानक रखता है - आपके पास बस एक बहुत ही तुच्छ कार्यक्रम और अधिक जटिल आरंभीकरण है।



2

एक अंग्रेजी शब्दार्थ की तरह लगता है। ओपी पहले कोड के अपने ब्लॉक को "कोड" और बाद में "प्रोग्राम" के रूप में संदर्भित करता है। उपयोगकर्ता कोड लिखता है, और फिर कंपाइलर प्रोग्राम लिखता है।


1

मुख्य को सभी वैश्विक चरों को आरंभ करने के बाद कहा जाता है।

मानक जो निर्दिष्ट नहीं करता है वह सभी मॉड्यूल और सांख्यिकीय रूप से जुड़े पुस्तकालयों के सभी वैश्विक चर के आरंभ का क्रम है।


0

हाँ, मुख्य कार्यान्वयन-विशिष्ट एक्सटेंशन को छोड़कर, हर C ++ प्रोग्राम का "एंट्री पॉइंट" है। फिर भी, कुछ चीजें मुख्य से पहले होती हैं, विशेष रूप से वैश्विक प्रारंभ जैसे कि मेन_रेट।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.