c++ - क्या 'int मुख्य' है एक वैध सी / सी ++ कार्यक्रम?





function main entry-point (9)


क्या यह एक वैध कार्यक्रम है?

नहीं।

यह एक कार्यक्रम नहीं है क्योंकि इसमें कोई निष्पादन योग्य भाग नहीं है।

क्या यह संकलन करने के लिए मान्य है?

हाँ।

क्या इसका उपयोग वैध प्रोग्राम के साथ किया जा सकता है?

हाँ।

वैध नहीं होने के लिए सभी संकलित कोड निष्पादन योग्य होने की आवश्यकता नहीं है। उदाहरण स्थिर और गतिशील पुस्तकालय हैं।

आपने प्रभावी रूप से ऑब्जेक्ट फ़ाइल बनाई है। यह वैध निष्पादन योग्य नहीं है, हालांकि एक और प्रोग्राम परिणामी फ़ाइल में इसे रनटाइम पर लोड करके ऑब्जेक्ट main से लिंक कर सकता है।

क्या यह एक त्रुटि होनी चाहिए?

पारंपरिक रूप से, सी ++ उपयोगकर्ता को उन चीजों को करने की अनुमति देता है जो ऐसा प्रतीत हो सकते हैं कि उनके पास कोई वैध उपयोग नहीं है लेकिन यह भाषा के वाक्यविन्यास के साथ फिट है।

मेरा मतलब है कि यकीन है, इसे एक त्रुटि के रूप में पुन: वर्गीकृत किया जा सकता है, लेकिन क्यों? यह क्या उद्देश्य होगा कि चेतावनी नहीं है?

जब तक इस कार्यक्षमता को वास्तविक कोड में उपयोग की जाने वाली सैद्धांतिक संभावना है, तो यह बहुत संभावना नहीं है कि main नामक गैर-फ़ंक्शन ऑब्जेक्ट होने से भाषा के अनुसार त्रुटि हो जाएगी।

मैं पूछता हूं क्योंकि मेरा कंपाइलर ऐसा सोचता प्रतीत होता है, भले ही मैं नहीं करता।

echo 'int main;' | cc -xc - -Wall
echo 'int main;' | c++ -x c++ - -Wall

Clang इस के साथ कोई चेतावनी या त्रुटि मुद्दों, और जीसीसी मुद्दों केवल नम्र चेतावनी: 'main' is usually a function [-Wmain] , लेकिन केवल सी के रूप में संकलित जब एक -std= निर्दिष्ट करना कोई फर्क नहीं पड़ता।

अन्यथा, यह ठीक से संकलित और लिंक करता है। लेकिन निष्पादन पर, यह तुरंत SIGBUS (मेरे लिए) के साथ समाप्त हो जाता है।

(उत्कृष्ट) उत्तरों के माध्यम से पढ़ना मुख्य () सी और सी ++ में वापस क्या होना चाहिए? और भाषा चश्मा के माध्यम से एक त्वरित grep, यह निश्चित रूप से मुझे लगता है कि एक मुख्य समारोह की आवश्यकता है। लेकिन जीसीसी के- -Wmain ('मुख्य' आमतौर पर एक समारोह है) (और यहां त्रुटियों की कमी) का -Wmain संभवतः अन्यथा सुझाव देता है।

पर क्यों? क्या इसके लिए कुछ अजीब एज-केस या "ऐतिहासिक" उपयोग है? किसी को पता है क्या देता है?

मेरा मुद्दा, मुझे लगता है, क्या मुझे सच में लगता है कि यह एक होस्टेड वातावरण में एक त्रुटि होनी चाहिए, आह?




मैं वास्तविक भाषा मानकों का हवाला देते हुए पहले से दिए गए उत्तरों में जोड़ना चाहता हूं।

क्या 'int मुख्य' है एक मान्य सी कार्यक्रम?

संक्षिप्त उत्तर (मेरी राय): केवल तभी जब आपका कार्यान्वयन "फ्रीस्टैंडिंग निष्पादन वातावरण" का उपयोग करता है।

C11 से निम्नलिखित सभी उद्धरण

5. पर्यावरण

एक कार्यान्वयन सी स्रोत फ़ाइलों का अनुवाद करता है और सी प्रोग्राम को दो डेटाप्रोसेसिंग-सिस्टम वातावरण में निष्पादित करता है , जिसे अनुवाद पर्यावरण और निष्पादन वातावरण कहा जाएगा [...]

5.1.2 निष्पादन वातावरण

दो निष्पादन वातावरण परिभाषित किए गए हैं: फ्रीस्टैंडिंग और होस्टेड। दोनों मामलों में, प्रोग्राम स्टार्टअप तब होता है जब निष्पादित वातावरण द्वारा नामित सी फ़ंक्शन को कॉल किया जाता है।

5.1.2.1 फ्रीस्टैंडिंग पर्यावरण

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

5.1.2.2 होस्टेड वातावरण

एक होस्टेड वातावरण प्रदान नहीं किया जाना चाहिए, लेकिन यदि मौजूद हो तो निम्नलिखित विनिर्देशों के अनुरूप होगा।

5.1.2.2.1 कार्यक्रम स्टार्टअप

कार्यक्रम स्टार्टअप में बुलाया गया समारोह मुख्य नाम दिया गया है। [...] इसे एक प्रकार के int के साथ परिभाषित किया जाएगा और बिना पैरामीटर [...] या दो पैरामीटर [...] या समकक्ष या कुछ अन्य कार्यान्वयन-परिभाषित तरीके से परिभाषित किया जाएगा।

इनमें से, निम्नलिखित मनाया जाता है:

  • एक सी 11 प्रोग्राम में एक फ्रीस्टैंडिंग या होस्टेड निष्पादन वातावरण हो सकता है और मान्य हो सकता है।
  • यदि यह एक फ्रीस्टैंडिंग है, तो एक मुख्य समारोह मौजूद नहीं होना चाहिए।
  • अन्यथा, प्रकार int की वापसी की वापसी के साथ एक होना चाहिए।

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

क्या 'int मुख्य' है वैध सी ++ प्रोग्राम?

संक्षिप्त उत्तर (मेरी राय): केवल तभी जब आपका कार्यान्वयन "फ्रीस्टैंडिंग निष्पादन वातावरण" का उपयोग करता है।

C++14 से उद्धरण

3.6.1 मुख्य समारोह

एक कार्यक्रम में मुख्य नामक वैश्विक कार्य शामिल होगा, जो प्रोग्राम की नामित शुरुआत है। यह क्रियान्वयन-परिभाषित किया गया है कि एक मुख्य कार्य को परिभाषित करने के लिए एक फ्रीस्टैंडिंग वातावरण में एक कार्यक्रम की आवश्यकता है या नहीं। [...] इसमें एक प्रकार का प्रकार int int होगा, लेकिन अन्यथा इसका प्रकार कार्यान्वयन-परिभाषित है। [...] मुख्य नाम अन्यथा आरक्षित नहीं है।

यहां, सी 11 मानक के विपरीत, फ्रीस्टैंडिंग निष्पादन पर्यावरण पर कम प्रतिबंध लागू होते हैं, क्योंकि कोई स्टार्टअप फ़ंक्शन का उल्लेख नहीं किया जाता है, जबकि होस्ट किए गए निष्पादन वातावरण के लिए, केस सी 11 के समान ही होता है।

दोबारा, मैं तर्क दूंगा कि होस्ट किए गए मामले के लिए, आपका कोड मान्य सी ++ 14 प्रोग्राम नहीं है, लेकिन मुझे यकीन है कि यह फ्रीस्टैंडिंग मामले के लिए है।

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




नहीं, यह एक वैध कार्यक्रम नहीं है।

सी ++ के लिए हाल ही में स्पष्ट रूप से दोष रिपोर्ट 1886 द्वारा खराब गठित किया गया था: मुख्य () के लिए भाषा संबंध जो कहता है:

मुख्य () को एक स्पष्ट भाषा संबंध देने पर कोई प्रतिबंध नहीं दिखता है, लेकिन शायद यह बीमार गठित या सशर्त रूप से समर्थित होना चाहिए।

और संकल्प के हिस्से में निम्नलिखित परिवर्तन शामिल थे:

एक कार्यक्रम जो वैश्विक दायरे में एक परिवर्तनीय मुख्य घोषित करता है या जो सी भाषा लिंकेज (किसी भी नामस्थान में) के साथ मुख्य नाम घोषित करता है, वह खराब है।

हम इस शब्द को नवीनतम सी ++ ड्राफ्ट मानक एन 4527 में पा सकते हैं जो सी ++ 1z ड्राफ्ट है।

क्लैंग और जीसीसी दोनों के नवीनतम संस्करण अब यह एक त्रुटि बनाते हैं ( इसे लाइव देखें ):

error: main cannot be declared as global variable
int main;
^

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




चूंकि प्रश्न सी और सी ++ के रूप में डबल-टैग किया गया है, इसलिए सी ++ और सी के लिए तर्क अलग होगा:

  • सी ++ विभिन्न प्रकार के टेक्स्ट समान रूप से समान प्रतीकों के बीच अंतर करने में मदद करने के लिए नाम मैंगलिंग का उपयोग करता है, उदाहरण के लिए एक ग्लोबल वेरिएबल xyz और एक फ्री-स्टैंडिंग ग्लोबल फ़ंक्शन xyz(int) । हालांकि, main नाम कभी गड़बड़ नहीं होता है।
  • सी मैंगलिंग का उपयोग नहीं करता है, इसलिए किसी प्रोग्राम के लिए एक अलग प्रतीक के स्थान पर एक प्रकार का प्रतीक प्रदान करके लिंकर को भ्रमित करना संभव है, और प्रोग्राम सफलतापूर्वक लिंक कर सकता है।

यही वह है जो यहां जा रहा है: लिंकर प्रतीक को main से ढूंढने की अपेक्षा करता है, और यह करता है। यह "तार" है कि प्रतीक यह एक समारोह था, क्योंकि यह किसी भी बेहतर नहीं जानता है। रनटाइम लाइब्रेरी का हिस्सा जो main से नियंत्रण को पास करता है main लिए लिंकर से पूछता है, इसलिए लिंकर इसे main प्रतीक देता है, जिससे लिंक चरण पूरा हो जाता है। बेशक यह रनटाइम पर विफल रहता है, क्योंकि main कार्य नहीं है।

यहां एक ही मुद्दे का एक और उदाहरण दिया गया है:

फ़ाइल एक्ससी:

#include <stdio.h>
int foo(); // <<== main() expects this
int main(){
    printf("%p\n", (void*)&foo);
    return 0;
}

फ़ाइल वाईसी:

int foo; // <<== external definition supplies a symbol of a wrong kind

संकलन:

gcc x.c y.c

यह संकलित करता है, और यह शायद चलाएगा, लेकिन यह अपरिभाषित व्यवहार है, क्योंकि संकलक के लिए वादा किए गए प्रतीक का प्रकार लिंकर को दिए गए वास्तविक प्रतीक से अलग है।

जहां तक ​​चेतावनी जाती है, मुझे लगता है कि यह उचित है: सी आपको उन पुस्तकालयों का निर्माण करने देता है जिनके पास कोई main कार्य नहीं है, इसलिए यदि आप किसी अज्ञात कारण के लिए एक चर main को परिभाषित करने की आवश्यकता है तो संकलक अन्य उपयोगों के लिए main नाम को मुक्त करता है।




मेरा मुद्दा, मुझे लगता है, क्या मुझे सच में लगता है कि यह एक होस्टेड वातावरण में एक त्रुटि होनी चाहिए, आह?

त्रुटि तुम्हारा है। आपने main नाम वाले फ़ंक्शन को निर्दिष्ट नहीं किया है जो एक int देता है और आपके प्रोग्राम को होस्ट किए गए वातावरण में उपयोग करने का प्रयास करता है।

मान लें कि आपके पास एक संकलन इकाई है जो main नाम वाले वैश्विक चर को परिभाषित करती है। यह एक फ्रीस्टैंडिंग वातावरण में कानूनी रूप से कानूनी हो सकता है क्योंकि फ्रीस्टैंडिंग वातावरण में कार्यान्वयन के लिए एक कार्यक्रम का गठन किया जाता है।

मान लीजिए कि आपके पास एक और संकलन इकाई है जो main नाम वाले वैश्विक फ़ंक्शन को परिभाषित करती है जो एक int देता है और कोई तर्क नहीं लेता है। यह एक मेजबान वातावरण में एक कार्यक्रम है जो वास्तव में है।

सब कुछ ठीक है अगर आप केवल फ्रीस्टैंडिंग वातावरण में पहली संकलन इकाई का उपयोग करते हैं और केवल होस्टेड वातावरण में दूसरे का उपयोग करते हैं। यदि आप एक कार्यक्रम में दोनों का उपयोग करते हैं तो क्या होगा? सी ++ में, आपने एक परिभाषा नियम का उल्लंघन किया है। वह अपरिभाषित व्यवहार है। सी में, आपने नियम का उल्लंघन किया है जो निर्देश देता है कि एक ही प्रतीक के सभी संदर्भ सुसंगत होना चाहिए; अगर वे अनिर्धारित व्यवहार नहीं हैं। अपरिभाषित व्यवहार एक "जेल से बाहर निकलना, मुफ़्त है!" कार्यान्वयन के डेवलपर्स को कार्ड। अपरिभाषित व्यवहार के जवाब में एक कार्यान्वयन कुछ भी मानक के अनुरूप है। कार्यान्वयन के बारे में चेतावनी नहीं है, अकेले पता लगाने, अपरिभाषित व्यवहार।

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

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




यह एक चेतावनी है क्योंकि यह तकनीकी रूप से अस्वीकृत नहीं है। स्टार्टअप कोड "मुख्य" के प्रतीक स्थान का उपयोग करेगा और तीन मानक तर्कों (argc, argv और envp) के साथ उस पर कूद जाएगा। यह नहीं है, और लिंक समय पर यह जांच नहीं सकता कि यह वास्तव में एक कार्य है, और न ही यह तर्क भी है। यही कारण है कि int main (int argc, char ** argv) काम करता है - कंपाइलर envp तर्क के बारे में नहीं जानता है और यह केवल उपयोग नहीं किया जाता है, और यह कॉलर-क्लीनअप है।

एक मजाक के रूप में, आप कुछ ऐसा कर सकते हैं

int main = 0xCBCBCBCB;

एक x86 मशीन पर और चेतावनियों और इसी तरह की चीजों को अनदेखा करते हुए, यह सिर्फ संकलित नहीं होगा बल्कि वास्तव में भी काम करेगा।

किसी ने इस तरह की एक तकनीक का उपयोग निष्पादन योग्य (प्रकार) लिखने के लिए किया जो कि कई आर्किटेक्चर पर सीधे चलता है - http://phrack.org/issues/57/17.html#article । इसका इस्तेमाल आईओसीसीसी - http://www.ioccc.org/1984/mullender/mullender.c जीतने के लिए भी किया जाता था।




main एक आरक्षित शब्द नहीं है, यह सिर्फ एक पूर्वनिर्धारित पहचानकर्ता है (जैसे cin , npos , npos ...), ताकि आप main नामक एक चर घोषित कर सकें, इसे प्रारंभ करें और उसके मूल्य को प्रिंट करें।

बेशक:

  • चेतावनी उपयोगी है क्योंकि यह काफी त्रुटि प्रवण है;
  • आपके पास main() फ़ंक्शन (लाइब्रेरीज़) के बिना एक स्रोत फ़ाइल हो सकती है।

संपादित करें

कुछ संदर्भ:

  • main आरक्षित शब्द नहीं है (सी ++ 11):

    फ़ंक्शन main उपयोग किसी प्रोग्राम के भीतर नहीं किया जाएगा। main का लिंक (3.5) कार्यान्वयन-परिभाषित है। एक प्रोग्राम जो हटाए गए मुख्य को परिभाषित करता है या जो मुख्य रूप से inline , static या constexpr होने की घोषणा करता है, वह खराब है। main नाम अन्यथा आरक्षित नहीं है। [उदाहरण: सदस्य कार्य, कक्षाएं और गणना main नाम कहा जा सकता है, क्योंकि अन्य नामस्थानों में इकाइयां हो सकती हैं। - अंत उदाहरण]

    सी ++ 11 - [basic.start.main] 3.6.1.3

    [2.11 / 3] [...] कुछ पहचानकर्ता सी ++ कार्यान्वयन और मानक पुस्तकालयों (17.6.4.3.2) द्वारा उपयोग के लिए आरक्षित हैं और अन्यथा इसका उपयोग नहीं किया जाएगा; कोई निदान की आवश्यकता नहीं है।

    [17.6.4.3.2 / 1] नाम और फ़ंक्शन हस्ताक्षर के कुछ सेट हमेशा कार्यान्वयन के लिए आरक्षित होते हैं:

    • प्रत्येक नाम जिसमें डबल अंडरस्कोर __ होता है या अंडरस्कोर के साथ शुरू होता है उसके बाद अपरकेस अक्षर (2.12) किसी भी उपयोग के लिए कार्यान्वयन के लिए आरक्षित होता है।
    • अंडरस्कोर से शुरू होने वाला प्रत्येक नाम वैश्विक नामस्थान में नाम के रूप में उपयोग के लिए कार्यान्वयन के लिए आरक्षित है।
  • प्रोग्रामिंग भाषाओं में आरक्षित शब्द

    संरक्षित शब्दों को प्रोग्रामर द्वारा फिर से परिभाषित नहीं किया जा सकता है, लेकिन पूर्वनिर्धारितता को अक्सर कुछ क्षमता में ओवरराइड किया जा सकता है। यह main मामला है: ऐसे क्षेत्र हैं जिनमें उस पहचानकर्ता का उपयोग करके घोषणा का अर्थ फिर से परिभाषित होता है।




सी के लिए अब तक कार्यान्वयन परिभाषित व्यवहार है।

चूंकि आईएसओ / आईईसी 9 8 99 कहता है:

5.1.2.2.1 कार्यक्रम स्टार्टअप

1 प्रोग्राम स्टार्टअप में बुलाया गया फ़ंक्शन मुख्य नाम दिया गया है। कार्यान्वयन इस समारोह के लिए कोई प्रोटोटाइप घोषित नहीं करता है। इसे एक प्रकार के int के साथ परिभाषित किया जाएगा और बिना पैरामीटर के:

int main(void) { /* ... */ }

या दो पैरामीटर के साथ (यहां argc और argv के रूप में संदर्भित किया गया है, हालांकि किसी भी नाम का उपयोग किया जा सकता है, क्योंकि वे उस फ़ंक्शन के लिए स्थानीय हैं, जिसमें उन्हें घोषित किया गया है):

int main(int argc, char *argv[]) { /* ... */ }

या उसके बराबर; या कुछ अन्य कार्यान्वयन-परिभाषित तरीके से।




In my case, I got the error because I had mixed UPPER- and lower-case package names on a Windows 7 system. Changing the package names to all lower case resolved the issue. Note also that in this scenario, I got no error compiling the .java file into a .class file; it just wouldn't run from the same (sub-sub-sub-) directory.





c++ c function main entry-point